Codeforces Round 934 (Div. 1)

Kur0n1ko發表於2024-04-26

LINK

CF1943A

簽到題

CF1943B

注意到對於k-bad的限制其實十分嚴格,考慮一個長為len的區間是k-bad的情況

\(len=k\),直接用manachar判斷

\(k=2k'\),仿照border推迴圈節的操作,該區間形如\(abab\),可以記錄每個字元的\(lastpos\),計算區間中\(pos-lastpos\)為2的位置個數

\(k=2k'+1\),迴圈節會在中間相交,該區間為\(aaa\)

mark

最開始想的方向是離線詢問區間然後考慮左右端點的移動,題解裡有類似的pam做法

CF1943C 000

注意到一次染色最多隻能對一條鏈上的兩個點產生影響。考慮樹的直徑。

\(len=2k+1\),則至少要\(k+1\)次操作

\(len=4k\),則對直徑間隔黑白染色,黑點關於一個白點對稱,白點同理,可以取到\(2k\)

\(len=4k+2\),一次操作最多會對同色兩個點產生影響,但同色點為奇數所以無法取到\(2k\)

mark

第三步的證明卡住了...腦殘一樣的...

腦殘了想在直徑上dp,但是連狀態都搞不出來...透過染色的方法來證明確實不錯...

CF1943D1

注意到一種情況合法當且僅當不存在 \(i\)\(a_i>a_{i+1}+a_{i-1}\)

若存在,顯然不行

若不存在,則一定可透過一次操作到另一種合法情況

dp隨便字首和最佳化一下就行了,可以滾

mark

有點神仙,如果沒看到過類似的結論大機率要000了,400的範圍很容易往區間dp想

更好的證明是操作相當於把差分陣列\(i<j\)\(d[i]+=1,d[j]-=1\),相當於是把正數與負數配對,考慮字首和

CF1943D2 000

codes

A
點選檢視程式碼
#include<iostream>
#include<cstdio>
#include<cstring>
#define I inline
using namespace std;

const int N = 200010;
int a[N],cnt[N];
int n; 

int main()
{
	int T; cin>>T;
	while(T--) {
		cin>>n;
		for(int i=1;i<=n;++i) cin>>a[i],cnt[a[i]]++;
		int ans=0,pd=1;
		for(int i=0;i<=n;++i) {
			if(cnt[i]==0) {
				ans=i;
				break;
			} else if(cnt[i]==1) {
				ans=i;
				if(pd) pd=0;
				else break;
			}
		}
		for(int i=1;i<=n;++i) cnt[a[i]]--;
		cout<<ans<<endl;
	}
 } 
B
點選檢視程式碼
#include<iostream>
#include<cstdio>
#include<cstring>
#define I inline
#define int long long
using namespace std;

const int N = 401000;
char a[N],ra[N];
int l[N],cnt[N][27],lastpos[27],pre[N],sum2[N];
int n,rn,m;

I void predeal() {
	ra[1]='*';
	for(int i=1;i<=n;++i) ra[i*2]='|',ra[i*2+1]=a[i];
	ra[n*2+2]='|'; ra[n*2+3]='?';
	ra[n*2+4]=ra[n*2+5]=0;
	rn=n*2+3;
}
I void nanachar() {
	int mr=0,mid=0;
	for(int i=1;i<=rn;++i) l[i]=0;
	for(int i=1;i<=rn;++i) {
		if(i<mr) l[i]=min(l[mid*2-i],mr-i+1);
		while(ra[l[i]+i]==ra[i-l[i]]) l[i]++;
		if(i+l[i]-1>mr) mr=i+l[i]-1,mid=i;
	}
} 
signed main()
{
	int T; cin>>T;
	while(T--) {
		cin>>n>>m;
		scanf("%s",a+1);
		n=strlen(a+1);
		for(int i=1;i<=n;++i)
			for(int j=1;j<=26;++j) cnt[i][j]=0;
		for(int i=1;i<=n;++i) {
			for(int j=1;j<=26;++j) cnt[i][j]=cnt[i-1][j];
			cnt[i][a[i]-'a'+1]++;
		}
		for(int i=0;i<=n;++i) pre[i]=sum2[i]=0;
		memset(lastpos,0,sizeof(lastpos));
		for(int i=1;i<=n;++i) {
			int ch=a[i]-'a'+1;
			pre[i]=lastpos[ch];
			lastpos[ch]=i;
			sum2[i]+=(i-pre[i]==2);
		}
		for(int i=1;i<=n;++i) sum2[i]+=sum2[i-1];
		
		predeal(); nanachar();	
	//	cout<<(ra+1)<<endl;
	//	for(int i=1;i<=rn;++i) cout<<l[i]<<' '; cout<<endl;
		for(int i=1;i<=m;++i) {
			int L,R,nlen; scanf("%lld",&L); scanf("%lld",&R); nlen=R-L+1; 
			int ans=0;
			
			int mid=L+R+1,len=(ra[mid]>='a'&&ra[mid]<='z')+(l[mid]-1)/2*2;
		//	cout<<"waao"<<len<<endl;
			if(len<nlen) ans+=nlen;
		//	cout<<"ans1"<<ans<<endl;
			int ch=a[R]-'a'+1,flag1=0;
			if(cnt[R][ch]-cnt[L-1][ch]!=nlen&&nlen>=3) {
				int mlen;
				if(nlen%2) mlen=nlen-1;
				else mlen=nlen-2;
				ans+=mlen*(mlen/2+1)/2;
				flag1=1;
			}
			//cout<<"ans2"<<ans<<endl;
			if(flag1&&(nlen>=4&&sum2[R]-sum2[L+1]!=(R-(L+1)))) {
				int mlen;
				if(nlen%2) mlen=nlen-2;
				else mlen=nlen-1;
				ans+=(mlen+1)*((mlen-1)/2+1)/2-1;
			} 
			
			printf("%lld\n",ans);
		}	
	}
	
}
/*
2
7 1
aaaaaaa
1 7
8 1
aaaaaaaa
1 8
*/
C
點選檢視程式碼
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#define I inline
using namespace std;

const int N = 20100;
vector<int> q[N],l;
int n,dep[N],f[N];

void dfs(int x,int fa) {
	f[x]=fa;
	dep[x]=dep[fa]+1;
	for(auto &t:q[x]) {
		if(t==fa) continue;
		dfs(t,x);
	}
}
int main()
{
	int T; cin>>T;
	while(T--) {
		cin>>n; l.clear();
		for(int i=1;i<=n;++i) q[i].clear();
		for(int i=1;i<n;++i) {
			int x,y; cin>>x>>y;
			q[x].push_back(y);
			q[y].push_back(x);
		}
		for(int i=1;i<=n;++i) dep[i]=0; 
		dfs(1,0);
		int mx1=1,mx2=1;
		for(int i=1;i<=n;++i) if(dep[i]>dep[mx1]) mx1=i;
		for(int i=1;i<=n;++i) dep[i]=0; 
		dfs(mx1,0);
		for(int i=1;i<=n;++i) if(dep[i]>dep[mx2]) mx2=i;
		while(1) {
			//cout<<mx2<<endl;
			l.push_back(mx2);
			mx2=f[mx2];
			if(!mx2) break;
		} //cout<<"sa";
		int len=l.size();// cout<<len<<endl;
		if(len%2) {
			cout<<len/2+1<<endl;
			for(int i=0;i<=len/2;++i) cout<<l[len/2]<<' '<<i<<endl;
		} else if(len%4==0){
			cout<<len/2<<endl;
			for(int i=1;i<=len/4;++i) cout<<l[len/2-1]<<' '<<i*2-1<<endl;
			for(int i=1;i<=len/4;++i) cout<<l[len/2]<<' '<<i*2-1<<endl;
		} else {
			cout<<len/2+1<<endl;
			for(int i=0;i<=len/2;++i) cout<<l[len/2]<<' '<<i<<endl;
		}
	}
}
D1
點選檢視程式碼
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#define I inline
#define int long long
using namespace std;

const int N = 410;
signed f[N][N][N],sm[N][N][N];
int n,k;
int mod;

I void Mod(signed &x) {
	x=(x>=mod?x-mod:x);
}
I void LMod(int &x) {
	x=(x>=mod?x-mod:x);
}
signed main()
{
	int T; cin>>T;
	while(T--) {
		cin>>n>>k>>mod;
		for(int i=0;i<=n;++i)
			for(int j=0;j<=k;++j)
				for(int p=0;p<=k;++p)
					f[i][j][p]=sm[i][j][p]=0;
		for(int i=0;i<=k;++i)
			for(int j=i;j<=k;++j)
				f[2][i][j]=sm[2][i][j]=1;
		for(int j=0;j<=k;++j)
			for(int p=k-1;p>=0;--p)
				sm[2][p][j]=f[2][p][j]+sm[2][p+1][j],Mod(sm[2][p][j]);
		for(int i=3;i<=n;++i) {
			for(int j=0;j<=k;++j) {
				for(int p=0;p<=k;++p) {
					int mn=max(0ll,j-p);
					f[i][j][p]+=sm[i-1][mn][j];
					Mod(f[i][j][p]);
				}
			}
			for(int j=0;j<=k;++j) {
				sm[i][k][j]=f[i][k][j];
				for(int p=k-1;p>=0;--p) {
					sm[i][p][j]=f[i][p][j]+sm[i][p+1][j],Mod(sm[i][p][j]);
				}		
			}			
		}
		int sum=0;
		for(int i=0;i<=k;++i)
			for(int j=0;j<=i;++j)
				sum+=f[n][i][j],LMod(sum);
		cout<<sum<<endl;
	}
}

相關文章