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;
}//
posted @ 2022-07-03 15:34  syzf2222  阅读(35)  评论(0编辑  收藏  举报