• 2022.7.3 CF516E&CF1137E


    CF1137E

    我们发现只有每一个段首才可能成为答案,套路地考虑到又只有下凸壳上的点才能成为答案。

    观察到下凸壳加等差数列还是下凸壳,我们只用每次摆平尾部翘起的部分即可。

    对于 \(1\) 操作,只用全部清空,然后新建一个节点就行;对于 \(2\) 操作,如果当前凸包的结尾不是 \(0\) 的话,我们就加一个点进去并维持其凸性;对于 \(3\) 操作,直接加 \(tag\) 然后摆平结尾就是。

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    #define db double
    const int maxn=1e6+10;
    const int mod=1e9+7;
    inline int read(){
    	int x=0,f=1;char c=getchar();
    	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    	while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
    	return x*f;
    }
    int n,m,K,B,top,lasop;
    struct node{
    	int x,y;
    	node operator-(node t){return (node){x-t.x,y-t.y};}
    	db operator*(node t){return (db)x*t.y-(db)y*t.x;}
    	bool operator>=(node t){return y+x*K>=t.y+t.x*K;}
    }a[maxn];
    signed main(){
    	n=read(),m=read();
    	a[top=1]=(node){0,0};
    	int op,k,b,s;
    	while(m--){
    		op=read();
    		if(op==1){
    			a[top=1]=(node){0,0};
    			K=B=0;n+=read();
    		}else if(op==2){
    			node p=(node){n,-K*n-B};n+=read();
    			if(lasop==3){
    				while(top>=2&&(p-a[top-1])*(a[top]-a[top-1])>0)--top;
    				a[++top]=p;
    			}
    		}else{
    			B+=read(),K+=read();
    			while(top>=2&&a[top]>=a[top-1])--top;
    		}printf("%lld %lld\n\n",a[top].x+1,a[top].y+B+K*a[top].x);
    		lasop=op;
    	}
    	return 0;
    }
    

    CF516E

    显然模 \(\gcd\) 不同的无关,我们只用考虑 \((n,m)=1\) 的情形。

    我们考虑 \(B\) 中最后的时间,同理可以做出 \(G\) 中最后的时间。既然只考虑 \(B\),我们希望所有操作与 \(G\) 无关。

    这也很好做到,显然若 \(x\) 有了,那么 \(n\) 时间后 \((x+m)%n\) 也会有,不难发现整个将形成一个大环。

    所以我们只用算出环上的编号,然后算每一段最远点的贡献就好。而重编号也是容易的,直接按 \(0,m,2m,3m,\cdots,(n-1)m\)\(n\) 取余这样编号就行。

    #include<bits/stdc++.h>
    using namespace std;
    #define inf 1e9
    const int maxn=2e5+10;
    const int mod=1e9+7;
    inline int read(){
    	int x=0,f=1;char c=getchar();
    	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    	while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
    	return x*f;
    }
    int n,m,b,g,gg;long long ans;
    vector<int>B[maxn],G[maxn];
    #define pb push_back
    #define vi vector<int>
    #define fi first
    #define se second
    map<int,int>mp;
    inline void exgcd(int &x,int &y,int a,int b){
    	if(!b){x=1,y=0;return;}
    	int tx,ty;
    	exgcd(tx,ty,b,a%b);
    	x=ty;
    	y=tx-(a/b)*ty;
    }
    inline int getinv(int a,int b){
    	int x,y;exgcd(x,y,a,b);
    	return (x%b+b)%b;
    }
    inline void work(vi B,int n,vi G,int m,int i){
    	if(B.size()==n)return;
    	int iv=getinv(m,n);long long res=-1;mp.clear();
    	for(auto x:B)mp[1ll*x*iv%n]=x;
    	for(auto x:G)if(mp.find(1ll*x*iv%n)==mp.end())
    		mp[1ll*x*iv%n]=x,res=x;
    	if(mp.size()==n)return void(ans=max(ans,res*gg+i));
    	mp[n+mp.begin()->fi]=mp.begin()->se;
    	for(auto it=mp.begin(),ti=++mp.begin();ti!=mp.end();it++,ti++)
    		res=max(res,1ll*(ti->fi-it->fi-1)*m+it->se);
    	ans=max(ans,res*gg+i);
    }
    int main(){
    	n=read(),m=read();
    	gg=__gcd(n,m);n/=gg,m/=gg;
    	if(gg>200000)return puts("-1")&0;
    	b=read();while(b--){int x=read();B[x%gg].pb(x/gg);}
    	g=read();while(g--){int x=read();G[x%gg].pb(x/gg);}
    	for(int i=0;i<gg;i++){
    		if(B[i].empty()&&G[i].empty())return puts("-1")&0;
    		sort(B[i].begin(),B[i].end());
    		sort(G[i].begin(),G[i].end());
    		work(B[i],n,G[i],m,i),work(G[i],m,B[i],n,i);
    	}printf("%lld\n",ans);
        return 0;
    }//
    
  • 相关阅读:
    PopupWindow设置动画效果
    android判断是否含有某权限
    每日一更提醒
    利用Pattern和Mather来禁止特殊字符的输入
    Android毛玻璃处理代码(Blur)
    how to render html tag
    数组
    复杂度分析
    书写markdown的利器
    cannot insert multiple commands into a prepared statement问题原因及解决办法
  • 原文地址:https://www.cnblogs.com/syzf2222/p/16439945.html
Copyright © 2020-2023  润新知