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;
}
}