【CF套题】Codeforces Round #528 (Div. 1)

版权声明:这是蒟蒻的BLOG,神犇转载也要吱一声哦~ https://blog.csdn.net/Dream_Lolita/article/details/85239751

【前言】
并不能打div2的我十分绝望。
虽然上分了还是很高兴。

【题目】
原题地址

A.Connect Three

将三个格子按 x x 排序后,中间那个格子向上下扩展,两边的格子再向中间连即可。

#include<bits/stdc++.h>
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;

typedef long long ll;
int mx,mi,ans;
pair<int,int> a[4];

int read()
{
	int ret=0,f=1;char c=getchar();
	while(!isdigit(c)) {if(c=='-')f=0;c=getchar();}
	while(isdigit(c)) ret=ret*10+(c^48),c=getchar();
	return f?ret:-ret;
}

int main()
{
#ifndef ONLINE_JUDGE
	freopen("A.in","r",stdin);
	freopen("A.out","w",stdout);
#endif
	mx=0;mi=1000;
	for(int i=1;i<=3;++i) 
	{	
		a[i].fi=read(),a[i].se=read();
		mx=max(mx,a[i].se);mi=min(mi,a[i].se);
	}
	sort(a+1,a+4);
	ans+=mx-mi+1;
	ans+=a[2].fi-a[1].fi;ans+=a[3].fi-a[2].fi;
	printf("%d\n",ans);
	for(int i=mi;i<=mx;++i) printf("%d %d\n",a[2].fi,i);
	for(int i=a[1].fi;i<a[2].fi;++i) printf("%d %d\n",i,a[1].se);
	for(int i=a[2].fi+1;i<=a[3].fi;++i) printf("%d %d\n",i,a[3].se);

	return 0;
}

B.Minimum Diameter Tree

边权在叶子的父边处贡献一定优于其他边,因此将边权平均分配给每个叶子的父边即可。设叶子数为 x x ,则答案就是 2 S n \frac {2S} n

#include<bits/stdc++.h>
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;

typedef long long ll;
typedef double db;
const int N=1e5+10;
int n,S,cnt,siz[N];

int read()
{
	int ret=0,f=1;char c=getchar();
	while(!isdigit(c)) {if(c=='-')f=0;c=getchar();}
	while(isdigit(c)) ret=ret*10+(c^48),c=getchar();
	return f?ret:-ret;
}

int main()
{
#ifndef ONLINE_JUDGE
	freopen("B.in","r",stdin);
	freopen("B.out","w",stdout);
#endif
	n=read();S=read();
	for(int i=1;i<n;++i)
	{
		int u=read(),v=read();
		++siz[u];++siz[v];
	}
	for(int i=1;i<=n;++i) if(siz[i]==1) ++cnt;
	printf("%.12lf\n",(db)S/(db)cnt*2);

	return 0;
}

C.Vasya and Templates

考虑 A A B B 第一个不同的位置,那么在这之前 S S 的置换一定是唯一确定的。在这之后,我们可以考虑 S S 是贴着上边界还是贴着下边界,或可以不贴着边界(即直接满足答案)。然后分情况讨论即可,细节比较多。

#include<bits/stdc++.h>
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;

typedef long long ll;
const int N=1e6+10,M=28;
int n,flag,ff,cnt;
int a[N],b[N],c[N];
int tg[M],cg[M],bo[M];
bool used[M],use[M];
char A[N],B[N],C[N];

int read()
{
	int ret=0,f=1;char c=getchar();
	while(!isdigit(c)) {if(c=='-')f=0;c=getchar();}
	while(isdigit(c)) ret=ret*10+(c^48),c=getchar();
	return f?ret:-ret;
}

void clear()
{
	flag=1;cnt=0;
	memset(used,0,sizeof(used));memset(use,0,sizeof(use));memset(tg,0,sizeof(tg));
	memset(bo,0,sizeof(bo));memset(cg,0,sizeof(cg));
}

void output()
{
	puts("YES");
	int j=1;
	for(int i=1;i<=cnt;++i)
	{
		if(tg[i]) cg[i]=tg[i];
		if(!cg[i]) 
		{
			while(used[j] || use[j]) ++j;
			cg[i]=j;use[j]=1;
		}
		putchar(cg[i]+'a'-1);
	}
	puts("");
}

void checkup(int p)
{
	for(int i=p+1;i<n;++i)
	{
		if(tg[c[i]]) 
		{
			if(tg[c[i]]>a[i]) return;
			if(tg[c[i]]==a[i]) continue;
			ff=0;break;
		}
		else 
		{
			for(int j=a[i]+1;j<=cnt;++j)
				if(!use[j]) {tg[c[i]]=j;use[j]=1;return;}
			if(!use[a[i]]) {tg[c[i]]=a[i];use[a[i]]=1;continue;} 
			ff=0;break;
		}
	}
}

void checkdown(int p)
{
	for(int i=p+1;i<n;++i)
	{
		if(tg[c[i]]) 
		{
			if(tg[c[i]]<b[i]) return;
			if(tg[c[i]]==b[i]) continue;
			ff=0;break;
		}
		else 
		{
			for(int j=1;j<b[i];++j)
				if(!use[j]) {tg[c[i]]=j;use[j]=1;return;}
			if(!use[b[i]]) {tg[c[i]]=b[i];use[b[i]]=1;continue;} 
			ff=0;break;
		}
	}
}

int main()
{
#ifndef ONLINE_JUDGE
	freopen("C.in","r",stdin);
	freopen("C.out","w",stdout);
#endif
	int T=read();
	while(T--)
	{
		clear();cnt=read();
		scanf("%s%s%s",C,A,B);n=strlen(C);
		if(strcmp(A,B)>0) {puts("NO");continue;}
		for(int i=0;i<n;++i) 
		{
			a[i]=A[i]-'a'+1,b[i]=B[i]-'a'+1,c[i]=C[i]-'a'+1;
			//cnt=max(cnt,a[i]);cnt=max(cnt,b[i]);cnt=max(cnt,c[i]);
		}
		int i;
		for(i=0;i<n;++i)
		{
			if(a[i]!=b[i]) break;
			if(cg[c[i]]) 
			{
				if(cg[c[i]]==a[i]) continue;
				else {flag=0;break;}
			}
			else 
			{
				if(used[a[i]]){flag=0;break;}
				cg[c[i]]=a[i],used[a[i]]=1;
			}
		}
		if(!flag) {puts("NO");continue;}
		if(i>=n){output();continue;}
		if(cg[c[i]])
		{
			if(cg[c[i]]>a[i] && cg[c[i]]<b[i]) {output();continue;}
			if(cg[c[i]]<a[i] || cg[c[i]]>b[i]) {puts("NO");continue;}
			ff=1;memcpy(tg,cg,sizeof(cg));memcpy(use,used,sizeof(used));
			if(cg[c[i]]==a[i]) checkup(i);
			else checkdown(i);
			if(ff) {output();continue;}
		}
		else
		{
			for(int j=a[i]+1;j<b[i];++j) if(!used[j]) {cg[c[i]]=j;used[j]=1;break;}
			if(cg[c[i]]>a[i] && cg[c[i]]<b[i]) {output();continue;}
			if(!used[a[i]]) 
			{
				memcpy(tg,cg,sizeof(cg));memcpy(use,used,sizeof(used));
				ff=1;tg[c[i]]=a[i];use[a[i]]=1;
				checkup(i);
				if(ff) {output();continue;}
			}
			if(!used[b[i]])
			{
				memcpy(tg,cg,sizeof(cg));memcpy(use,used,sizeof(used));
				ff=1;tg[c[i]]=b[i];use[b[i]]=1;
				checkdown(i);
				if(ff) {output();continue;}
			}
		}
		puts("NO");
	}

	return 0;
}

D.Rock-Paper-Scissors Champion

考虑一个人能成为胜者的充要条件,则为他的左右两边都有能被它(严格)打败的人或没有能赢他的人。因为我们用 set \text{set} 维护出每个东西的第一个和最后一个人并用 BIT \text{BIT} 维护一个前缀人数就可以计算答案了。

#include<bits/stdc++.h>
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;

typedef long long ll;
const int N=2e5+10,M=3;
int n,Q,ans;
char s[N];
set<int>st[M];

int read()
{
	int ret=0,f=1;char c=getchar();
	while(!isdigit(c)) {if(c=='-')f=0;c=getchar();}
	while(isdigit(c)) ret=ret*10+(c^48),c=getchar();
	return f?ret:-ret;
}

struct BIT
{
	#define lowbit(x) (x&(-x))
	int c[N];
	void update(int x,int v){for(;x<N;x+=lowbit(x))c[x]+=v;}
	int query(int x){int res=0;for(;x;x-=lowbit(x))res+=c[x];return res;}
}bit[M];

int id(char c){if(c=='R')return 0;else if(c=='S')return 1;return 2;}
int calc(int p)
{
	int win=(p+1)%M,lose=(p-1+M)%M;
	if(st[p].empty()) return bit[win].query(n);
	if(st[lose].empty()) return 0;
	return bit[win].query(n)-bit[win].query(max(*st[p].rbegin(),*st[lose].rbegin()))+
		   bit[win].query(*st[lose].rbegin())-bit[win].query(*st[lose].begin())+
		   bit[win].query(min(*st[p].begin(),*st[lose].begin()));
}

int main()
{
#ifndef ONLINE_JUDGE
	freopen("D.in","r",stdin);
	freopen("D.out","w",stdout);
#endif
	n=read();Q=read();scanf("%s",s+1);
	for(int i=1;i<=n;++i)
	{
		int p=id(s[i]);
		bit[p].update(i,1);st[p].insert(i);
	}
	ans=calc(0)+calc(1)+calc(2);
	printf("%d\n",ans);
	while(Q--)
	{
		int p=read();char ch;scanf("%c",&ch);
		if(s[p]==ch){printf("%d\n",ans);continue;}
		int las=id(s[p]),now=id(ch);s[p]=ch;
		bit[las].update(p,-1);bit[now].update(p,1);
		st[las].erase(p);st[now].insert(p);
		ans=calc(0)+calc(1)+calc(2);
		printf("%d\n",ans);
	}
	return 0;
}

E.Beautiful Matrix

考虑枚举哪一位的字典序给定矩阵来计算答案,那么我们实际上要处理的就是一个类似错排的问题。现在考虑第 i i 行第 j j 列的字典序小于给定矩阵,那么这一位放置的数字有两种情况:用了第 i 1 i-1 行第 j j 列及以后的数字或没有用,分开进行贡献即可。

还要处理的一个问题是如何计算 n n 个数字的错排但其中的 k k 个可以任意放置的方案数。设这个东西为 f n , k f_{n,k} ,那么我们有 f n , k = f n , k 1 f n 1 , k 1 f_{n,k}=f_{n,k-1}-f_{n-1,k-1} ,特别地, f n , 0 = n ! , 0 ! = 1 f_{n,0}=n!,0!=1

#include<bits/stdc++.h>
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;

typedef long long ll;
const int N=2005,mod=998244353;
int n,a[N][N];
ll ans,fac[N],f[N][N];

int read()
{
	int ret=0,f=1;char c=getchar();
	while(!isdigit(c)) {if(c=='-')f=0;c=getchar();}
	while(isdigit(c)) ret=ret*10+(c^48),c=getchar();
	return f?ret:-ret;
}

struct BIT
{
	#define lowbit(x) (x&(-x))
	ll c[N];
	void clear(){memset(c,0,sizeof(c));}
	void update(int x,ll v){for(;x<N;x+=lowbit(x))c[x]+=v;}
	void upzero(int x){ll t=Query(x,x);update(x,-t);}
	ll query(int x){ll res=0;for(;x;x-=lowbit(x))res+=c[x];return res;}
	ll Query(int l,int r){return query(r)-query(l-1);}
}bit1,bit2;
ll upm(ll x){return x<0?x+mod:x;}
void up(ll &x,ll y){x+=y;if(x>=mod)x-=mod;}

int main()
{
#ifndef ONLINE_JUDGE
	freopen("E.in","r",stdin);
	freopen("E.out","w",stdout);
#endif
	n=read();
	fac[0]=1;for(int i=1;i<=n;++i)fac[i]=fac[i-1]*i%mod;
	for(int i=0;i<=n;++i) 
	{
		f[i][0]=fac[i];
		for(int j=1;j<=i;++j) f[i][j]=upm(f[i][j-1]-f[i-1][j-1]);
	}
	for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) a[i][j]=read();
	for(int i=1;i<=n;++i) bit1.update(i,1);
	for(int i=1;i<=n;++i) 
	{
		up(ans,bit1.query(a[1][i]-1)*fac[n-i]%mod);
		bit1.update(a[1][i],-1);
	}
	for(int i=2;i<=n;++i) 
	{
		ans=ans*f[n][n]%mod;
		bit1.clear();bit2.clear();
		for(int j=1;j<=n;++j) bit1.update(j,1),bit2.update(j,1);
		for(int j=1;j<=n;++j)
		{
			bit2.upzero(a[i-1][j]);
			int s1=bit1.query(a[i][j]-1),s2=bit2.query(a[i][j]-1);
			int s3=bit2.query(n);
			if(a[i][j]>a[i-1][j] && bit1.Query(a[i-1][j],a[i-1][j])) --s1;
			up(ans,(s1-s2+mod)*f[n-j][s3]%mod);
			if(s3>0) up(ans,s2*f[n-j][s3-1]%mod);
			bit1.update(a[i][j],-1);bit2.upzero(a[i][j]);
		}
	}
	printf("%lld\n",upm(ans%mod));
	
	return 0;
}

F.Forest Fires

不会做,我们直接贴上zzq的代码。

#include <iostream>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
#include <string>
#include <bitset>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <algorithm>
#include <sstream>
#include <stack>
#include <iomanip>
using namespace std;
#define pb push_back
#define mp make_pair
typedef pair<int,int> pii;
typedef long long ll;
typedef double ld;
typedef vector<int> vi;
#define fi first
#define se second
#define fe first
#define FO(x) {freopen(#x".in","r",stdin);freopen(#x".out","w",stdout);}
#define Edg int M=0,fst[SZ],vb[SZ],nxt[SZ];void ad_de(int a,int b){++M;nxt[M]=fst[a];fst[a]=M;vb[M]=b;}void adde(int a,int b){ad_de(a,b);ad_de(b,a);}
#define Edgc int M=0,fst[SZ],vb[SZ],nxt[SZ],vc[SZ];void ad_de(int a,int b,int c){++M;nxt[M]=fst[a];fst[a]=M;vb[M]=b;vc[M]=c;}void adde(int a,int b,int c){ad_de(a,b,c);ad_de(b,a,c);}
#define es(x,e) (int e=fst[x];e;e=nxt[e])
#define esb(x,e,b) (int e=fst[x],b=vb[e];e;e=nxt[e],b=vb[e])
#define SZ 666666
#define yn yyn
int n,t,x[SZ],y[SZ];
int ys[SZ],yn;
pair<int,pair<pii,int> > os[SZ]; int on;
const int M=128;
pii operator + (pii a,pii b)
{
	if(a.fi<b.fi) return a;
	if(b.fi<a.fi) return b;
	return pii(a.fi,a.se+b.se);
}
pii seg[SZ]; int tg[SZ],ls[SZ],rs[SZ];
void pd(int x)
{
	if(!tg[x]) return;
	seg[x].fi+=tg[x];
	if(x<=M)
		tg[x+x]+=tg[x],tg[x+x+1]+=tg[x];
	tg[x]=0;
}
void upd(int x)
{
	pd(x+x); pd(x+x+1);
	seg[x]=seg[x+x]+seg[x+x+1];
}
void edt(int x,int l,int r,int v)
{
	if(l>r||rs[x]<l||r<ls[x]) return;
	pd(x);
	if(l<=ls[x]&&rs[x]<=r)
	{
		tg[x]+=v; return;
	}
	edt(x+x,l,r,v);
	edt(x+x+1,l,r,v);
	upd(x);
}
map<int,ll> rss;
ll calc(int s)
{
	if(rss.count(s)) return rss[s];
	yn=0;
	for(int i=1;i<=n;++i)
		ys[++yn]=y[i]-s,ys[++yn]=y[i]+s+1;
	sort(ys+1,ys+1+yn); yn=unique(ys+1,ys+1+yn)-ys-1;
	int tot=ys[yn]-ys[1]; on=0;
	for(int i=1;i<=n;++i)
	{
		int L=lower_bound(ys+1,ys+1+yn,y[i]-s)-ys,
		R=lower_bound(ys+1,ys+1+yn,y[i]+s+1)-ys;
		os[++on]=mp(x[i]-s,mp(pii(L,R-1),1));
		os[++on]=mp(x[i]+s+1,mp(pii(L,R-1),-1));
	}
	sort(os+1,os+1+on);
	for(int i=1;i<=M+M;++i) seg[i]=pii(0,0),tg[i]=0;
	for(int i=1;i<yn;++i) seg[i+M]=pii(0,ys[i+1]-ys[i]);
	for(int i=M-1;i>=1;--i) seg[i]=seg[i+i]+seg[i+i+1];
	ll ans=0;
	for(int i=1;i<=on;++i)
		edt(1,os[i].se.fi.fi,os[i].se.fi.se,os[i].se.se),
		ans+=(tot-seg[1].se)*ll(os[i+1].fi-os[i].fi);
	return rss[s]=ans;
}
ll cd(int s)
{
	return calc(s)-calc(s-1);
}
const int MOD=998244353;
ll S1(ll x)
{return x*(x+1)/2%MOD;}
ll S2(ll x)
{
	ll t[]={x,x+1,2*x+1};
	for(int i=0;i<3;++i)
		if(t[i]%2==0) {t[i]/=2; break;}
	for(int i=0;i<3;++i)
		if(t[i]%3==0) {t[i]/=3; break;}
	return t[0]*(ll)t[1]%MOD*t[2]%MOD;
}
bool cp(ll l,ll r)
{
	if(l>=r) return 1;
	return cd(r)-cd(l)==(r-l)*(cd(l+1)-cd(l));
}
int main()
{
	for(int i=1;i<=M;++i) ls[i+M]=rs[i+M]=i;
	for(int i=M-1;i>=1;--i) ls[i]=ls[i+i],rs[i]=rs[i+i+1];
//	n=50,t=1e6;
	cin>>n>>t;
	for(int i=1;i<=n;++i)
//		x[i]=rand()*32+rand(),y[i]=rand()*32+rand();
		cin>>x[i]>>y[i];
//	ll aa=0;
//	for(int i=1;i<=t;++i) aa+=cd(i)*i,aa%=MOD;
//	cout<<aa<<"\n";
//	return 0;
	ll L=1,ans=0;
	while(L<=t)
	{
		if(L==t)
		{
			ans+=cd(L)%MOD*L;
			ans%=MOD;
			break;
		}
		ll u=cd(L+1)-cd(L);
		ll l=L+1,r=t;
		while(l<r)
		{
			ll m=(l+r+1)>>1;
			if(cd(m)-cd(m-1)!=u
			||(!cp(L,m))||(!cp(L,m-1))
			||(!cp(L,m-2))||(!cp(L,m-3)))
				r=m-1;
			else l=m;
		}
		ll b=cd(L),n=l-L;
		b%=MOD; u%=MOD;
		//(b+u*i)*(i+L)  i in [0,n]
		ans+=S2(n)*u+S1(n)*((u*L+b)%MOD)+L*b%MOD*(n+1);
		ans%=MOD;
		L=l+1;
	}
	ans=(ans%MOD+MOD)%MOD;
	cout<<ans<<"\n";
}

猜你喜欢

转载自blog.csdn.net/Dream_Lolita/article/details/85239751