Codeforces Round #512 (Div. 1) 简要题解

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_35649707/article/details/82837775

传送门

Vasya and Triangle

用叉积来计算面积就可以知道最后面积一定是 0.5 的倍数,也就是把 k k n m nm 约分后最后为 1 1 或者 2 2 。 然后分两种情况讨论即可。

#include <bits/stdc++.h>
using namespace std;

const int RLEN=1<<18|1;
inline char nc() {
	static char ibuf[RLEN],*ib,*ob;
	(ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
	return (ib==ob) ? -1 : *ib++;
} 
inline int rd() {
	char ch=nc(); int i=0,f=1;
	while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();}
	while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
	return i*f;
}

long long n,m,k,nn,mm; 
int main() {
	cin>>n>>m>>k;
	nn=n; mm=m;
	long long t=__gcd(n,k);
	n/=t; k/=t;
	t=__gcd(m,k);
	m/=t; k/=t;
	if(k>2) {puts("NO"); return 0;}
	puts("YES");
	if(k==2) {cout<<0<<' '<<0<<' '<<n<<' '<<0<<' '<<0<<' '<<m<<'\n';}
	else {
		if(n<nn) n*=2;
		else m*=2;
		cout<<0<<' '<<0<<' '<<n<<' '<<0<<' '<<0<<' '<<m<<'\n';
	}
}

Vasya and Good Sequences

一段区间合法那么 s u m sum 是偶数且 m a x s u m 2 max \le \frac{sum}{2} 。 注意到区间长度大于 64 64 就只与前缀奇偶有关了,可以记两个前缀和。小于暴力枚举。

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;

const int RLEN=1<<18|1;
inline char nc() {
	static char ibuf[RLEN],*ib,*ob;
	(ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
	return (ib==ob) ? -1 : *ib++;
} 
inline int rd() {
	char ch=nc(); int i=0,f=1;
	while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();}
	while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
	return i*f;
}

const int N=3e5+50, LIM=150;
int n,a[N],p1[N],p2[N];

int main() {
	cin>>n; p2[0]=1;
	for(int i=1;i<=n;i++) {
		LL x; cin>>x;
		a[i]=__builtin_popcountll(x)+a[i-1];
		if(a[i]&1) ++p1[i]; else ++p2[i];
		p1[i]+=p1[i-1]; p2[i]+=p2[i-1];
	}
	long long ans=0;
	for(int i=1;i<=n;i++) {
		int l=max(1,i-LIM+1);
		if(l!=1) {
			if(a[i]&1) ans+=p1[l-2];
			else ans+=p2[l-2];
		}
		int mx=a[i]-a[i-1];
		for(int j=i;j>=l;j--) {
			if((mx<=(a[i]-a[j-1])/2) && (!((a[i]-a[j-1])&1))) ++ans;
			if(j!=1) mx=max(mx,a[j-1]-a[j-2]);
		}
	} cout<<ans<<'\n';
} 

Putting Boxes Together

容易知道最优点在带权中位数处,线段树+二分。

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;

const int RLEN=1<<18|1;
inline char nc() {
	static char ibuf[RLEN],*ib,*ob;
	(ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
	return (ib==ob) ? -1 : *ib++;
} 
inline int rd() {
	char ch=nc(); int i=0,f=1;
	while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();}
	while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
	return i*f;
} 
inline void W(LL x) {
	static int buf[50];
	if(!x) {putchar('0'); return;}
	if(x<0) {putchar('-'); x=-x;}
	while(x) {buf[++buf[0]]=x%10; x/=10;}
	while(buf[0]) {putchar(buf[buf[0]--]+'0');}
}

const int N=2e5+50, mod=1e9+7;
struct node {
	int cnt;
	LL lpos,rpos,s,sl,sr;
	node() {sl=sr=0;} 
} tr[N*4];
int n,q,a[N],w[N];

inline node merge(node L,node R) {
	node t; t.cnt=L.cnt+R.cnt;
	t.lpos=L.lpos; t.rpos=R.rpos;
	t.s=L.s+R.s;
	t.sl=(L.sl+R.sl+(R.rpos-R.cnt-L.rpos)*(L.s%mod))%mod;
	t.sr=(R.sr+L.sr+(R.lpos-L.lpos-L.cnt)*(R.s%mod))%mod;
	return t;
}

inline void build(int k,int l,int r) {
	if(l==r) {
		tr[k].cnt=1;
		tr[k].lpos=tr[k].rpos=a[l];
		tr[k].s=w[l];
		return;
	} int mid=(l+r)>>1;
	build(k<<1,l,mid);
	build(k<<1|1,mid+1,r);
	tr[k]=merge(tr[k<<1],tr[k<<1|1]);
}
inline void inc(int k,int l,int r,int p) {
	if(l==r) {
		tr[k].cnt=1;
		tr[k].lpos=tr[k].rpos=a[l];
		tr[k].s=w[l];
		return;
	} int mid=(l+r)>>1;
	if(p<=mid) inc(k<<1,l,mid,p);
	else inc(k<<1|1,mid+1,r,p);
	tr[k]=merge(tr[k<<1],tr[k<<1|1]);
}
inline LL ask_sum(int k,int l,int r,int L,int R) {
	if(L>R) return 0;
	if(L<=l && r<=R) return tr[k].s;
	int mid=(l+r)>>1;
	if(R<=mid) return ask_sum(k<<1,l,mid,L,R);
	else if(L>mid) return ask_sum(k<<1|1,mid+1,r,L,R);
	else return ask_sum(k<<1,l,mid,L,R)+ask_sum(k<<1|1,mid+1,r,L,R);
}
inline node ask(int k,int l,int r,int L,int R) {
	if(L<=l && r<=R) return tr[k];
	int mid=(l+r)>>1;
	if(R<=mid) return ask(k<<1,l,mid,L,R);
	else if(L>mid) return ask(k<<1|1,mid+1,r,L,R);
	else return merge(ask(k<<1,l,mid,L,R),ask(k<<1|1,mid+1,r,L,R));
}

int main() {
	n=rd(), q=rd();
	for(int i=1;i<=n;i++) a[i]=rd();
	for(int i=1;i<=n;i++) w[i]=rd();
	build(1,1,n);
	for(int i=1;i<=q;i++) {
		int x=rd(), y=rd();
		if(x<0) {
			w[-x]=y;
			inc(1,1,n,-x); 
		} else {
			int l=x, r=y, ans=l;
			while(l<=r) {
				int mid=(l+r)>>1;
				LL lc=ask_sum(1,1,n,x,mid);
				LL rc=ask_sum(1,1,n,mid+1,y);
				if(lc>=rc) ans=mid, r=mid-1;
				else l=mid+1;
			}
			ans=(ask(1,1,n,x,ans).sl+ask(1,1,n,ans,y).sr)%mod;
			W(ans), putchar('\n');
		}
	}
}

Linear Congruential Generator

最后每个函数图象呈 ρ \rho 型,且进入环之前的链长最多为 1 1

答案为 l c m c 1 , c 2 , . . . , c n lcm _{c_1,c_2,...,c_n} +最长链长,于是从大到小贪心即可。

#include <bits/stdc++.h>
using namespace std;

const int RLEN=1<<18|1;
inline char nc() {
	static char ibuf[RLEN],*ib,*ob;
	(ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
	return (ib==ob) ? -1 : *ib++;
}
inline int rd() {
	char ch=nc(); int i=0,f=1;
	while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();}
	while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
	return i*f;
}

const int N=2e6+50, mod=1e9+7;
int pr[N],pt,npr[N],mnpr[N];
int n,p[N],c[N],mx[N];

inline void sieve() {
	for(int i=2;i<N;i++) {
		if(!npr[i]) pr[++pt]=i, mnpr[i]=i;
		for(int j=1;j<=pt;j++) {
			long long k=i*pr[j];
			if(k>=N) break;
			mnpr[k]=pr[j];
			npr[k]=1;
			if(!(i%pr[j])) break;
		}
	}
}
int main() {
	sieve();
	n=rd();
	for(int i=1;i<=n;i++) p[i]=rd();
	sort(p+1,p+n+1);
	int bz=0, ans=1;
	for(int i=n;i>=1;i--) {
		if(!c[p[i]]) ++c[p[i]], ans=(long long)ans*p[i]%mod, mx[p[i]]=1;
		else {
			int v=--p[i]; 
			while(v!=1) {
				int u=mnpr[v], ci=0;
				while(!(v%u)) v/=u, ++ci;
				if(c[u]<ci) {
					for(int j=c[u]+1;j<=ci;j++) ans=(long long)ans*u%mod;
					c[u]=ci; mx[u]=1;
				} else mx[u]+=(c[u]==ci);
			}
		}
	}
	for(int i=1;i<=n;i++) {
		int v=p[i], tag=0; 
		while(v!=1) {
			int u=mnpr[v], ci=0;
			while(!(v%u)) v/=u, ++ci;
			if(c[u]==ci && mx[u]==1) tag=1;
		}
		if(!tag) {++ans; break;}
	}
	cout<<ans<<'\n';
}

Euler tour

如果区间包含,且一个数出现的奇偶位置不同,则一定不合法。

否则依次构造每个区间,不断舍弃形容 y , x , y y,x,y 的相邻三个数的后两个即可判断有无合法解,顺便构造出合法解。

#include <bits/stdc++.h>
using namespace std;

const int RLEN=1<<18|1;
inline char nc() {
	static char ibuf[RLEN],*ib,*ob;
	(ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
	return (ib==ob) ? -1 : *ib++;
}
inline int rd() {
	char ch=nc(); int i=0,f=1;
	while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();}
	while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
	return i*f;
}

const int N=1e6+50, L=21;
int n,a[N],c[N],li[N],ri[N],pre[N],lst[N],mn[N][21];
vector <int> unvis;
inline int ga(int *anc,int x) {return (anc[x]==x) ? x : (anc[x]=ga(anc,anc[x]));}
inline void solve(int l,int r) {
	vector <int> vec; int p=-1;
	for(int i=ga(ri,l);i<=r;i=ga(ri,i+1)) {
		vec.push_back(i); ++p;
		while(vec.size()>=3) {
			if(((!a[vec[p-2]] && a[i]) || (a[vec[p-2]] && !a[i]) || (a[vec[p-2]] && (a[vec[p-2]]==a[i]))) && a[vec[p-1]] ) {
				if(a[vec[p-2]]!=a[vec[p]])a[vec[p-2]]=a[i]=a[vec[p-2]]+a[i];
				vec.pop_back(); vec.pop_back();
				p-=2;
			} else break;
		}
	}	
	
	for(int j=1;j<vec.size();++j) if(a[vec[j]] && a[vec[j-1]]) {puts("no"); exit(0);}
	
	deque <int> q; int nowl=vec[0];
	for(int j=1;j<vec.size()-1;++j) q.push_back(vec[j]);
	while(!q.empty()) {
		int u=q.front(), v=q.back();
		if(q.size()==1) {
			if(!a[u]) {
				if(unvis.empty()) {puts("no"); exit(0);}
				a[u]=unvis.back(); unvis.pop_back();
			} break;
		} else {
			if(!a[u] && !a[v]) {
				if(unvis.empty()) {puts("no"); exit(0);}
				a[u]=a[v]=unvis.back(); unvis.pop_back();
				nowl=a[u]; q.pop_front(); q.pop_back();
			} else if(a[u]) {
				a[q[1]]=nowl; q.pop_front(); q.pop_front();
			} else {
				a[q[q.size()-2]]=nowl; q.pop_back(); q.pop_back();
			}
		}
	}
	for(int i=ga(ri,l);i<=r;i=ga(ri,i+1)) if(i!=l) ri[i]=r+1;
	li[r]=l;
}

inline void solve2() {
	if(unvis.size()) {
		a[1]=a[2*n-1]=unvis.back(); unvis.pop_back();
		solve(1,2*n-1); return;
	}
	vector <int> vec; int p=-1;
	for(int i=1;i<2*n;i=ga(ri,i+1)) {vec.push_back(i); ++p;}	
	int c0=0, c1=0;
	for(int j=0;j<vec.size();++j) if(a[vec[j]]) ++c1;
	for(int j=1;j<p;j++) {
		if(!a[vec[j]]) continue;
		--c1;
		if(vec[j]&1) {
			if(j>=2*c0 && p-j>=2*c1) {
				a[1]=a[2*n-1]=a[vec[j]]; solve(1,2*n-1);
				return;
			}
		}
		++c0;
	}
	puts("no"); exit(0);
}
int main() {
	n=rd();
	for(int i=1;i<2*n;i++) {
		a[i]=rd(); ++c[a[i]];
	}
	for(int i=1;i<=n;i++) if(!c[i]) unvis.push_back(i);
	
	if(a[1] && a[2*n-1] && a[1]!=a[2*n-1]) {puts("no"); return 0;}
	else if((a[1] || a[2*n-1]) && (a[1]!=a[2*n-1])) {a[1]=a[2*n-1]=a[1]+a[2*n-1];}
	
	for(int i=1;i<2*n;i++) {
		if(!a[i]) continue;
		pre[i]=(lst[a[i]] ? lst[a[i]] : i);
		lst[a[i]]=i;
	}
	
	for(int i=1;i<2*n;i++) {
		mn[i][0]=(pre[i] ? pre[i] : i);
		if(a[i] && ((i-pre[i])%2)) {puts("no"); return 0;}
		for(int j=1;j<L && (i>=(1<<j));j++) mn[i][j]=min(mn[i][j-1],mn[i-(1<<(j-1))][j-1]);
		if(a[i] && pre[i]<i) {
			int mx=i, pos=i-1;
			for(int j=L-1;~j;j--) if(pos-(1<<j)+1>pre[i]) mx=min(mx,mn[pos][j]), pos-=(1<<j);
			if(mx<=pre[i]) {puts("no"); return 0;}
		}
	}
	
	for(int i=1;i<=2*n;i++) ri[i]=i, li[i]=i;
	for(int i=2;i<2*n;i++) if(a[i] &&  ga(li,pre[i])<i) 
		solve(ga(li,pre[i]),i);
	
	if(!a[1] && !a[2*n-1]) solve2();
	puts("yes");
	for(int i=1;i<2*n;i++) printf("%d ",a[i]);
}

猜你喜欢

转载自blog.csdn.net/qq_35649707/article/details/82837775