CF专练

  • CF1562
    • A The Miracle and the Sleeper
    • B Scenes From a Memory
    • C Rings
    • D Two Hundred Twenty One
    • E Rescue Niwen!
  • CF1567
    • A Domino Disaster
    • B MEXor Mixup
    • C Carrying Conundrum
    • D Expression Evaluation Error
    • E Non-Decreasing Dilemma
  • CF1561
    • A Simply Strange Sort
    • B. Charmed by the Game
    • C Deep Down Below
    • D Up the Strip
    • E. Bottom-Tier Reversals
  • 1560
    • D Make a Power of Two
    • E Polycarp and String Transformation
    • F2 Nearest Beautiful Number (hard version)
  • 1559
    • A Mocha and Math
    • B Mocha and Red and Blue
    • C Mocha and Hiking
    • D Mocha and Diana (Hard Version)
    • E Mocha and Stars
  • 1557
    • A Ezzat and Two Subsequences
    • B Moamen and k-subarrays
    • C Moamen and XOR
  • 1549
    • A Gregor and Cryptography
    • B Gregor and the Pawn Game
    • Web of Lies
    • D Integers Have Friends
  • CF1555
    • D Say No to Palindromes
    • E Boring Segments
    • F Good Graph
  • CF1554
    • A Cherry
    • C Mikasa
    • D Diane
    • CF1546D AquaMoon and Chess
    • CF1542C Strange Function
    • CF1542D Priority Queue

CF1562

A The Miracle and the Sleeper

TP
考虑一个数,取模比他小的数模数的最大值一定是(a+1)/2(a+1)/2(a+1)/2
同时aaa要取得越大越好
考虑lll,如果l>a/2l>a/2l>a/2 直接最大值为r%lr\%lr%l
反之为(a+1)/2(a+1)/2(a+1)/2

#include <bits/stdc++.h>
using namespace std;
const int maxn = 5e4+5;
int readint(){int x=0,f=1;char s=getchar();#define sc (s=getchar())while(s<'0'||s>'9'){if(s=='-')f=-1;sc;}while(s>='0'&&s<='9'){x=(x<<3)+(x<<1)+(s^48);sc;}#undef screturn x*f;
}
int main (){int t=readint();while(t--){int a=readint(),b=readint();if(a>b/2)printf("%d\n",b%a);elseprintf("%d\n",((b+1)>>1)-1); } return 0;
}

B Scenes From a Memory

TP
考虑如果有1,4,6,8,91,4,6,8,91,4,6,8,9直接输出就行了
反之只剩下2,3,5,72,3,5,72,3,5,7,如果其中有一个的个数超过两个就直接输出2,aa2,aa2,aa
剩下就是大家都为一个,讨论情况易得

#include <bits/stdc++.h>
using namespace std;
const int maxn = 5e4+5;
int readint(){int x=0,f=1;char s=getchar();#define sc (s=getchar())while(s<'0'||s>'9'){if(s=='-')f=-1;sc;}while(s>='0'&&s<='9'){x=(x<<3)+(x<<1)+(s^48);sc;}#undef screturn x*f;
}
char s[55];
int cnt[10];
int main (){int t=readint();while(t--){memset(cnt,0,sizeof(cnt));int n=readint();scanf("%s",s+1);int flag=0;for(int i=1;i<=n;i++){int num=s[i]-'0';cnt[num]++;if(num==1||num==4||num==6||num==8||num==9){printf("1\n%d\n",num);flag=1;break;}}if(flag)continue;for(int i=1;i<=9;i++){if(cnt[i]>=2){printf("2\n%d%d\n",i,i);flag=1;break;}}if(flag)continue;puts("2");for(int i=1;i<=n;i++){int num=s[i]-'0';if(num==2){cnt[2]--;if(cnt[5])puts("25"),flag=1;else if(cnt[7])puts("27"),flag=1;}if(num==3){cnt[3]--;if(cnt[5])puts("35"),flag=1;else if(cnt[2])puts("32"),flag=1;}if(num==5){cnt[5]--;if(cnt[2])puts("52"),flag=1;else if(cnt[7])puts("57"),flag=1;}if(num==7){cnt[7]--;if(cnt[5])puts("75"),flag=1;else if(cnt[2])puts("72"),flag=1;}if(flag==1)break;}}return 0;
}

C Rings

TP
开头傻逼了,没想到前导零也算
那么有000的时候直接取前面或者后面(看那一边大于n/2n/2n/2即可)
如果没有000,那就全是111,取两个相等长度的即可

#include <bits/stdc++.h>
using namespace std;
const int maxn = 5e4+5;
int readint(){int x=0,f=1;char s=getchar();#define sc (s=getchar())while(s<'0'||s>'9'){if(s=='-')f=-1;sc;}while(s>='0'&&s<='9'){x=(x<<3)+(x<<1)+(s^48);sc;}#undef screturn x*f;
}
char s[maxn];
int main (){int t=readint();while(t--){int n=readint();scanf("%s",s+1);bool flag=0;for(int i=1;i<=n;i++){if(s[i]=='0'){flag=1;if(i>n/2)printf("1 %d 1 %d\n",i,i-1);elseprintf("%d %d %d %d\n",i,n,i+1,n);break;} }if(!flag){printf("1 %d 2 %d\n",n-1,n);}}return 0;
}

D Two Hundred Twenty One

TP
先考虑整个串,如果发现当前区间满足情况,直接输出000
如果当前区间长度为奇数,那么只需要删除一个即可,因为贡献是逐渐累积的,设这个区间贡献为sss,你一定可以在一个位置找到他的前面的贡献是s/2s/2s/2,后面为s/2s/2s/2,
如果为偶数,先任意删一个位置,在按奇数的方法选择
接下来考虑删除位置,也就是考虑奇数长度删哪里,由上面所说,设删除的位置为kkk,也就是l→(k−1)l\to (k-1)l→(k−1)的贡献,等于(k+1)→r(k+1)\to r(k+1)→r
也就是说pre[k−1]−pre[l−1]=pre[r]−pre[k]pre[k-1]-pre[l-1]=pre[r]-pre[k]pre[k−1]−pre[l−1]=pre[r]−pre[k]
移项pre[k−1]+pre[k]=pre[l−1]+pre[r]pre[k-1]+pre[k]=pre[l-1]+pre[r]pre[k−1]+pre[k]=pre[l−1]+pre[r]
然后先预处理,再去查找(离散化和大常数STLSTLSTL都可以)懒狗就是我

#include <bits/stdc++.h>
using namespace std;
const int maxn = 3e5+5;
int readint(){int x=0,f=1;char s=getchar();#define sc (s=getchar())while(s<'0'||s>'9'){if(s=='-')f=-1;sc;}while(s>='0'&&s<='9'){x=(x<<3)+(x<<1)+(s^48);sc;}#undef screturn x*f;
}
char s[maxn];
int sum[maxn];
map<int,set<int> > mp;
int main (){int t=readint();while(t--){int n=readint(),m=readint();scanf("%s",s+1);mp.clear();sum[0]=0;for(int i=1;i<=n;i++) {sum[i]=sum[i-1]+((s[i]=='+')?1:-1)*((i&1)?1:-1);mp[sum[i]+sum[i-1]].insert(i);}for(int i=1;i<=m;i++){int x=readint(),y=readint();if(sum[y]-sum[x-1]==0)puts("0");else{ if((y-x)&1){puts("2"),printf("%d ",y);y--;}elseputs("1");int pos=*mp[sum[y]+sum[x-1]].lower_bound(x);printf("%d\n",pos);}}}return 0;
}

E Rescue Niwen!

TP
易得,选了以iii号位开头的,那么全都选
像abc⋅⋅⋅⋅⋅⋅abc······abc⋅⋅⋅⋅⋅⋅,只选前三个,后面再遇到abcabcabc显然个数要少一些(感性理解,我并不知道末尾大小影响会造成啥)
然后求一个LCPLCPLCP后再做dpdpdp即可
(我打死不会说我是用SASASA结果还是用n2n^2n2求的)

#include <bits/stdc++.h>
using namespace std;
const int maxn = 5e3+5;
int readint(){int x=0,f=1;char s=getchar();#define sc (s=getchar())while(s<'0'||s>'9'){if(s=='-')f=-1;sc;}while(s>='0'&&s<='9'){x=(x<<3)+(x<<1)+(s^48);sc;}#undef screturn x*f;
}
char s[maxn];
int cnt[maxn],maxsize;
int sa[maxn],rk[maxn];
int x[maxn<<1],y[maxn<<1];
int lcp[maxn][maxn];
int height[maxn];
int dp[maxn];
void get_sa(int n){int maxsize=150;for(int i=0;i<=maxsize;i++)cnt[i]=0;for(int i=0;i<=n*2+5;i++)x[i]=0,y[i]=0;for(int i=1;i<=n;i++){x[i]=s[i];cnt[x[i]]++; } for(int i=1;i<=maxsize;i++)cnt[i]+=cnt[i-1];for(int i=n;i>=1;i--)sa[cnt[x[i]]--]=i;for(int k=1;k<=n;k<<=1){int num=0;for(int i=n-k+1;i<=n;i++)y[++num]=i;for(int i=1;i<=n;i++)if(sa[i]>k)y[++num]=sa[i]-k;for(int i=1;i<=maxsize;i++)cnt[i]=0;for(int i=1;i<=n;i++)++cnt[x[i]];for(int i=1;i<=maxsize;i++)cnt[i]+=cnt[i-1];for(int i=n;i>=1;i--)sa[cnt[x[y[i]]]--]=y[i],y[i]=0;swap(x,y);x[sa[1]]=1;num=1;for(int i=2;i<=n;i++)x[sa[i]]=(y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k])?num:++num;if(num==n)break;maxsize=num;}
}
void getheight(int n){for(int i=1;i<=n;i++)rk[sa[i]]=i;
//  cout<<rk[2]<<" "<<rk[3]<<endl;int k=0;for(int i=1;i<=n;i++){if(rk[i]==1)continue;if(k)k--;int j=sa[rk[i]-1];while(i+k<=n&&j+k<=n&&s[j+k]==s[i+k]) k++;height[rk[i]]=k;}
}
void getlcp(int n){for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)lcp[i][j]=0;for(int i=1;i<=n;i++){lcp[i][i]=n-sa[i]+1;for(int j=i+1;j<=n;j++)lcp[i][j]=min(lcp[i][j-1],height[j]);        }for(int i=1;i<=n;i++)for(int j=i-1;j;j--)lcp[i][j]=lcp[j][i];
}
int main (){int t=readint();while(t--){int n=readint();scanf("%s",s+1);get_sa(n);getheight(n);getlcp(n);for(int i=1;i<=n;i++)dp[i]=0;dp[1]=n; for(int i=2;i<=n;i++){dp[i]=n-i+1;for(int j=1;j<=i-1;j++){if(rk[j]>rk[i]||lcp[rk[i]][rk[j]]==n-i+1)continue;      dp[i]=max(dp[i],dp[j]+n-i+1-lcp[rk[i]][rk[j]]);}}int maxx=0;for(int i=1;i<=n;i++){maxx=max(dp[i],maxx);}printf("%d\n",maxx);}return 0;
}

CF1567

TP

A Domino Disaster

不做评价

#include <bits/stdc++.h>
using namespace std;
const int maxn = 5e3+5;
int readint(){int x=0,f=1;char s=getchar();#define sc (s=getchar())while(s<'0'||s>'9'){if(s=='-')f=-1;sc;}while(s>='0'&&s<='9'){x=(x<<3)+(x<<1)+(s^48);sc;}#undef screturn x*f;
}
char s[105];
int main (){int t=readint();while(t--){int n=readint();scanf("%s",s+1);for(int i=1;i<=n;i++){if(s[i]=='U')printf("D");if(s[i]=='L')printf("L");if(s[i]=='R')printf("R");if(s[i]=='D')printf("U");}puts("");} return 0;
}

B MEXor Mixup

TP
不做评价

#include <bits/stdc++.h>
using namespace std;
const int maxn = 3e5+5;
int readint(){int x=0,f=1;char s=getchar();#define sc (s=getchar())while(s<'0'||s>'9'){if(s=='-')f=-1;sc;}while(s>='0'&&s<='9'){x=(x<<3)+(x<<1)+(s^48);sc;}#undef screturn x*f;
}
int pre[maxn];
int main (){int t=readint();for(int i=1;i<=3e5;i++)pre[i]=pre[i-1]^i;while(t--){int a=readint(),b=readint();int sum=pre[a-1],num=a;if(sum==b)printf("%d\n",num);else if((b^sum)!=a)printf("%d\n",num+1);elseprintf("%d\n",num+2);} return 0;
}

C Carrying Conundrum

TP
考虑到奇数位加到奇数位,偶数位加到偶数位,分开讨论即可

#include <bits/stdc++.h>
using namespace std;
const int maxn = 3e5+5;
int readint(){int x=0,f=1;char s=getchar();#define sc (s=getchar())while(s<'0'||s>'9'){if(s=='-')f=-1;sc;}while(s>='0'&&s<='9'){x=(x<<3)+(x<<1)+(s^48);sc;}#undef screturn x*f;
}
int pre[maxn];
char s[15];
int main (){int t=readint();while(t--){scanf("%s",s+1);int n=strlen(s+1);int len1=0,len2=0;for(int i=1;i<=n;i++){if(i&1)len1=len1*10+(s[i]^48);elselen2=len2*10+(s[i]^48);}printf("%d\n",(len2+1)*(len1+1)-2);}return 0;
}

D Expression Evaluation Error

TP
显然,保留最高位是最优秀的方案,借位保证个数先向低位借

#include <bits/stdc++.h>
using namespace std;
int readint(){int x=0,f=1;char s=getchar();#define sc (s=getchar())while(s<'0'||s>'9'){if(s=='-')f=-1;sc;}while(s>='0'&&s<='9'){x=(x<<3)+(x<<1)+(s^48);sc;}#undef screturn x*f;
}
int getlog10(int num){int ans=1;for(int i=1;;i++){ans*=10;if(ans>num)return i-1;}
}
int main (){int t=readint();while(t--){int s=readint(),n=readint();while(1){if(n==1){printf("%d\n",s);break;}int num=pow(10,getlog10(s-n+1));printf("%d ",num);s-=num;n--;}}return 0;
}/

E Non-Decreasing Dilemma

TP
最开始的想法就是找出每段连续不下降的字串,但是查询和修改跟本解决不了,于是线段树,只需要注意中间拼接的问题,也就是mergemergemerge,刚开始不写结构体mergemergemerge不动,查询直接给我人干麻

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 2e5+5;
int readint(){int x=0,f=1;char s=getchar();#define sc (s=getchar())while(s<'0'||s>'9'){if(s=='-')f=-1;sc;}while(s>='0'&&s<='9'){x=(x<<3)+(x<<1)+(s^48);sc;}#undef screturn x*f;
}
struct node{int lx,rx,len;int suml,sumr;LL ans;
}tree[maxn<<2];
node merge(node x,node y){node final;final.lx=x.lx,final.rx=y.rx;final.len=x.len+y.len;final.ans=x.ans+y.ans;if(x.rx<=y.lx){final.ans+=1ll*x.sumr*y.suml;if(x.suml==x.len)final.suml=x.suml+y.suml;elsefinal.suml=x.suml;if(y.sumr==y.len)final.sumr=y.sumr+x.sumr;elsefinal.sumr=y.sumr;}elsefinal.suml=x.suml,final.sumr=y.sumr;return final;
}
void build(int x,int l,int r){if(l==r){tree[x].lx=tree[x].rx=readint();tree[x].len=tree[x].suml=tree[x].sumr=tree[x].ans=1;return;}int mid=(l+r)>>1;build(x<<1,l,mid);build(x<<1|1,mid+1,r);tree[x]=merge(tree[x<<1],tree[x<<1|1]);
}
void update(int x,int l,int r,int pos,int val){if(l==r){tree[x].lx=tree[x].rx=val;return;}int mid=(l+r)>>1;if(pos<=mid)update(x<<1,l,mid,pos,val);elseupdate(x<<1|1,mid+1,r,pos,val);tree[x]=merge(tree[x<<1],tree[x<<1|1]);
}
node query(int x,int l,int r,int goal_l,int goal_r){if(goal_l<=l&&goal_r>=r)return tree[x];int mid=(l+r)>>1;if(goal_r<=mid)return query(x<<1,l,mid,goal_l,goal_r);else if(goal_l>mid)return query(x<<1|1,mid+1,r,goal_l,goal_r);elsereturn merge(query(x<<1,l,mid,goal_l,goal_r),query(x<<1|1,mid+1,r,goal_l,goal_r));
}
int main (){int n=readint(),q=readint();build(1,1,n);while(q--){int op=readint();if(op==1){int pos=readint(),val=readint();update(1,1,n,pos,val);}else{int l=readint(),r=readint();printf("%lld\n",query(1,1,n,l,r).ans);}}return 0;
}

CF1561

A Simply Strange Sort

TP
模拟题,复杂度不会算

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 1e3+5;
int readint(){int x=0,f=1;char s=getchar();#define sc (s=getchar())while(s<'0'||s>'9'){if(s=='-')f=-1;sc;}while(s>='0'&&s<='9'){x=(x<<3)+(x<<1)+(s^48);sc;}#undef screturn x*f;
}
int a[maxn];
int main(){int t=readint();while(t--){int n=readint();for(int i=1;i<=n;i++)a[i]=readint();int st=1,i=0;while(1){bool flag=1;for(int j=1;j<=n;j++){if(a[j]!=j)flag=0;}if(flag){printf("%d\n",i);break; }st=i%2+1;for(int j=st;j<n;j+=2){if(a[j]>a[j+1])swap(a[j],a[j+1]);}i++;}}return 0;
}

B. Charmed by the Game

TP
先考虑最下情况,交替胜利且为保守球,后来多出来的单独排序,然后把前面的交替胜利一对一对互换,可以的到所有值,但是如果后面多出来的是奇数,那么要分类讨论哪一个人先发球

#include <bits/stdc++.h>
using namespace std;
int readint(){int x=0,f=1;char s=getchar();#define sc (s=getchar())while(s<'0'||s>'9'){if(s=='-')f=-1;sc;}while(s>='0'&&s<='9'){x=(x<<3)+(x<<1)+(s^48);sc;}#undef screturn x*f;
}
int FABS(int x){if(x<0)x=-x;return x;
}
vector<int> g;
int main (){int t=readint();while(t--){int a=readint(),b=readint();int delta=FABS(a-b);if(a==b)g.push_back(0);else if(delta==1)g.push_back(0),g.push_back(1);else{if(delta&1)g.push_back(delta/2),g.push_back(delta/2+1);elseg.push_back(delta/2);}if(a<b)swap(a,b);for(int i=1;i<=b;i++){if(delta&1)g.push_back(delta/2+i*2),g.push_back(i*2+delta/2+1);elseg.push_back(delta/2+i*2);}printf("%d\n",(int)g.size());for(int i=0;i<g.size();i++){printf("%d ",g[i]);}g.clear();puts("");}return 0;
}

C Deep Down Below

TP
排序即可

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
typedef long long LL;
int readint(){int x=0,f=1;char s=getchar();#define sc (s=getchar())while(s<'0'||s>'9'){if(s=='-')f=-1;sc;}while(s>='0'&&s<='9'){x=(x<<3)+(x<<1)+(s^48);sc;}#undef screturn x*f;
}
int FABS(int x){if(x<0)x=-x;return x;
}
int delta[maxn],ind[maxn];
int k[maxn];
bool cmp(int x,int y){return delta[x]<delta[y];
}
int main (){int t=readint();while(t--){memset(delta,0,sizeof(delta));int n=readint();for(int i=1;i<=n;i++){ind[i]=i;k[i]=readint();int a=readint(),ans;delta[i]=ans=a+1;for(int j=2;j<=k[i];j++){ans++;a=readint();if(a>=ans){int t=ans;ans=a+1;delta[i]+=(ans-t);}}}sort(ind+1,ind+n+1,cmp);int sum,need;sum=need=delta[ind[1]];for(int i=2;i<=n;i++){sum+=k[ind[i-1]];if(sum<delta[ind[i]]){need+=(delta[ind[i]]-sum);sum+=(delta[ind[i]]-sum);}}printf("%d\n",need);}return 0;
}

D Up the Strip

设dp[i]dp[i]dp[i]为改到i的方案数
通过减法转移的dp[i+1]→dp[n]dp[i+1]\to dp[n]dp[i+1]→dp[n]
假设通过除aaa得到的dp[i∗a]→dp[i∗a+a−1]dp[i*a]\to dp[i*a+a-1]dp[i∗a]→dp[i∗a+a−1]
调和级数+++后缀和

#include <bits/stdc++.h>
using namespace std;
const int maxn = 4e6+5;
typedef long long LL;
int readint(){int x=0,f=1;char s=getchar();#define sc (s=getchar())while(s<'0'||s>'9'){if(s=='-')f=-1;sc;}while(s>='0'&&s<='9'){x=(x<<3)+(x<<1)+(s^48);sc;}#undef screturn x*f;
}
int FABS(int x){if(x<0)x=-x;return x;
}
int dp[maxn],suf[maxn];
int main (){int n=readint(),mo=readint();dp[n]=suf[n]=1;for(int i=n-1;i>=1;i--){dp[i]=suf[i+1];for(int j=2;j*i<=n;j++){dp[i]=(0ll+dp[i]+suf[j*i]-suf[min(j*i+j,n+1)])%mo;dp[i]=(dp[i]+mo)%mo;}suf[i]=(0ll+suf[i+1]+dp[i])%mo;
//      cout<<dp[i]<<endl;}printf("%d\n",dp[1]);return 0;
}

E. Bottom-Tier Reversals

TP
因为每次翻转的个数为奇数,那么翻转后位置的奇偶无法改变
如果奇数在偶数位上,或者偶数在奇数位上那就一辈子坐牢
考虑两两一组,将从小的大的翻转,只不过要倒序,才能保证过后的翻转不会有影响,具体看实现吧

#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e3+50;
int readint(){int x=0,f=1;char s=getchar();#define sc (s=getchar())while(s<'0'||s>'9'){if(s=='-')f=-1;sc;}while(s>='0'&&s<='9'){x=(x<<3)+(x<<1)+(s^48);sc;}#undef screturn x*f;
}
int a[maxn],ans[maxn<<2],cnt;
int FABS(int x){if(x<0)x=-x;return x;
}
int find(int n,int x){for(int i=1;i<=n;i++)if(a[i]==x)return i;
}
void change(int x){for(int i=1,j=x;i<=x/2;i++,j--)swap(a[i],a[j]);ans[++cnt]=x;
}
int main(){int t=readint();
//  cout<<t<<endl;while(t--){int n=readint();cnt=0;bool flag=0;for(int i=1;i<=n;i++)a[i]=readint();for(int i=1;i<=n;i++)if(FABS(a[i]-i)%2==1){puts("-1");flag=1;break;}if(flag)continue;for(int i=1;i<=n/2;i++){int pos1=find(n,i*2-1);change(pos1);int pos2=find(n,i*2);change(pos2-1);change(pos2+1);change(3);change(n-i*2+2);}change(n);printf("%d\n",cnt);for(int i=1;i<=cnt;i++){printf("%d ",ans[i]);}puts("");}return 0;
}

1560

D Make a Power of Two

TP
搞清楚右边加数位的可以是任何数就可以了

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
int readint(){int x=0,f=1;char s=getchar();#define sc (s=getchar())while(s<'0'||s>'9'){if(s=='-')f=-1;sc;}while(s>='0'&&s<='9'){x=(x<<3)+(x<<1)+(s^48);sc;}#undef screturn x*f;
}
char c[25];
struct zz{char s[25];int len;
};
vector<zz>g;
void prepare(){LL num=1;zz t;t.s[1]='1';t.len=1;g.push_back(t);for(int i=1;i<=60;i++){num<<=1ll;LL tot=num;t.len=0;while(tot){t.s[++t.len]=48^(tot%10);tot/=10;}reverse(t.s+1,t.s+t.len+1);g.push_back(t);}
}
int main (){int t=readint();prepare();
//  for(int i=0;i<g.size();i++){//      for(int j=1;j<=g[i].len;j++){//          printf("%c",g[i].s[j]);
//      }
//      puts("");
//  }while(t--){scanf("%s",c+1);int n=strlen(c+1);int ans=0x3f3f3f3f;for(int i=0;i<g.size();i++){int k=1;for(int j=1;j<=n;j++)if(k<=g[i].len&&c[j]==g[i].s[k])++k;k--;ans=min(ans,n+g[i].len-k-k);}printf("%d\n",ans);}return 0;
}

E Polycarp and String Transformation

TP
口胡一个题
可以统计每个字母的最后出现的位置,然后排序得到他是第几个删除的,然后第iii轮删除的字母的出现个数一定是iii的倍数,逆向得到开头初串,然后模拟判可行性

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=100005;
const int inf=1<<30;
const ll inff=1ll<<60;
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^48);c=getchar();}return x*f;
}
string s,s1,s2,s3;
int l,f[35],ans[35],cnt;
void solve(){cin>>s;int sz=s.size();for(int i=0;i<26;i++)f[i]=0;cnt=0;for(int i=sz-1;i>=0;i--){//倒序处理,得到第二问的解if(!f[s[i]-'a'])ans[++cnt]=s[i]-'a';f[s[i]-'a']++;}//注意我们求出来的第二问的解实际上也是倒序的,//但是由于我比较懒就没有数组翻转了l=0;for(int i=1;i<=cnt;i++)if(f[ans[i]]%(cnt-i+1)!=0){//cnt-i+1即ans[i]出现的轮数puts("-1");//这个解已经不合法了return;}else l+=f[ans[i]]/(cnt-i+1);//求出初始串的长度ls1="",s2="";for(int i=0;i<l;i++)s1+=s[i];int now=cnt;//接下来是模拟,检验解的合法性//s1为当前的字符串,s2为字符串对应的串t,s3用来更新s1while(s1!=""){s2+=s1;s3="";sz=s1.size();for(int i=0;i<sz;i++)if(ans[now]!=s1[i]-'a')s3+=s1[i];s1=s3;now--;}//cout<<s2<<'\n';if(s2==s){//如果检验得到的串t与给出的串t相同,那么这个解是合法的for(int i=0;i<l;i++)cout<<s[i];cout<<' ';for(int i=cnt;i;i--)putchar(ans[i]+'a');puts("");}else puts("-1");//解不合法,输出-1
}
int main(){int tests=1;tests=read();
while(tests--){solve();
}   return 0;
}

F2 Nearest Beautiful Number (hard version)

TP
这题挺水的,觉得不值210021002100,显然,要让的到的数最小,必须让他前缀相同的越多,所以用setsetset不断塞数,如果大于可以用的数字,就向前找离他最近的那位不是999的数位++++++,然后将nnn更新,因为已经知道那其间已经没有满足要求的数了,向上紧逼

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
int readint(){int x=0,f=1;char s=getchar();#define sc (s=getchar())while(s<'0'||s>'9'){if(s=='-')f=-1;sc;}while(s>='0'&&s<='9'){x=(x<<3)+(x<<1)+(s^48);sc;}#undef screturn x*f;
}
char s[15];
int main (){int t=readint();while(t--){scanf("%s",s+1);int k=readint();int n=strlen(s+1);while(1){set<char> st;st.clear();for(int i=1;i<=n;i++)st.insert(s[i]);if(st.size()<=k){for(int i=1;i<=n;i++)printf("%c",s[i]);puts("");break;}st.clear();int pos=1;while(pos<=n){st.insert(s[pos]);if(st.size()>k){while(s[pos]=='9')pos--;s[pos]++;for(int i=pos+1;i<=n;i++)s[i]='0';break;}pos++;}}}return 0;
}

1559

A Mocha and Math

TP
数学题还是一个废物,考虑一个数位取和不能增加这一位为111的数字的个数,所以每个数字的都为111的数位才能保留,这有意思

#include <bits/stdc++.h>
using namespace std;
int readint(){int x=0,f=1;char s=getchar();#define sc (s=getchar())while(s<'0'||s>'9'){if(s=='0')f=-1;sc;}while(s>='0'&&s<='9'){x=(x<<3)+(x<<1)+(s^48);sc;}#undef screturn x*f;
}
int main (){int t=readint();while(t--){int n=readint();int ans=readint();for(int i=2;i<=n;i++){ans&=readint();}printf("%d\n",ans);}return 0;
}

B Mocha and Red and Blue

TP
写dpdpdp写麻了,我定义的是dp[i][0/1][0/1]dp[i][0/1][0/1]dp[i][0/1][0/1]当前位置为B/RB/RB/R的情况下最大串的最小值,以及当前连续位置串长度的最小值
哦,伞兵了,突然发现不是最长连续段,是指和前面相同的个数有多少个,自己想复杂了,mdmdmd
看看这俩兄弟的吧
模拟版
dp版

C Mocha and Hiking

TP
细想发现有三种情况可以完成整个路程
n+1n+1n+1号城市可通向 111 号城市。
nnn 号城市可通向 n+1n + 1n+1 号城市。
某座编号 kkk的城市能通向 n+1n+1n+1 号城市,且 n+1n + 1n+1 号城市能通向 k+1k + 1k+1 号城市。

#include<iostream>
#include<cstdio>
using namespace std;
int t,n;
int a[10005];
bool qwq;
int main(){cin>>t;for(int ii=1;ii<=t;ii++){qwq=0;cin>>n;for(int i=1;i<=n;i++)cin>>a[i];if(a[1]==1){cout<<n+1<<" ";for(int i=1;i<=n;i++)cout<<i<<" ";cout<<"\n";continue;}if(a[n]==0){for(int i=1;i<=n+1;i++)cout<<i<<" ";cout<<"\n";continue;}for(int i=1;i<=n-1;i++)if(a[i]==0&&a[i+1]==1){for(int j=1;j<=i;j++)cout<<j<<" ";cout<<n+1<<" ";for(int j=i+1;j<=n;j++)cout<<j<<" ";cout<<"\n";qwq=1;break;  }if(qwq==0)cout<<"-1\n";}return 0;
}

D Mocha and Diana (Hard Version)

TP
真牛逼,说实话不看题解把我卖了都想不到
先证明小的那棵树连通块的个数一定为111
设小的为AAA,大的为BBB
假设AAA如今已经不能操作了,任意条边相连都会影响BBB图为树
设AAA中其中有两个树x,yx,yx,y
由于不能再连边了,所以两颗树的任何节点在另一个森林中都可以联通
所以其中有一个连通块一定为111个
由此贪心分析可知,随意加可行边即可。
考虑优化贪心。

考虑一个中心点 sss。
我们先让所有点与 sss 尝试连边。
然后连完后令 AAA 图中与 sss 不连通的点集为 LLL,BBB 图中与 sss 不连通的点集为 RRR。
显然 L∩R=∅L\cap R=\varnothingL∩R=∅。
考虑 l∈Ll\in Ll∈L 和 r∈Rr\in Rr∈R。
由定义有 A 图中 lll 与 sss 不连通,rrr 与 sss 连通,BBB 图相反。
那么任意lll与rrr 都可连边。
然后只要随意配对完 LLL 或 RRR 就行了,此时一幅图变成一个连通块。
时间复杂度 O(nα(n))O(n\alpha(n))O(nα(n))。

E Mocha and Stars

TP
如果不考虑gcdgcdgcd的话,就是一个裸的背包,考虑gcdgcdgcd后可以考虑一个容斥
在处理 gcd⁡\gcdgcd 为 xxx 的问题时,可以倒着枚举一个 iii,设 ansians_iansi​是 gcd⁡\gcdgcd 恰好为iii 的方案数,
fif_ifi​为 gcd⁡\gcdgcd 是 iii 的倍数的方案数。
那么就可以用 ansg=fg−∑2m/gansi∗gans_g = f_g - \sum_{2}^{m/g} ans_{i*g}ansg​=fg​−∑2m/g​ansi∗g​ 来求解。
很好的博客

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
const int mo = 998244353;
int readint(){int x=0,f=1;char s=getchar();#define sc (s=getchar())while(s<'0'||s>'9'){if(s=='-')f=-1;sc;}while(s>='0'&&s<='9'){x=(x<<3)+(x<<1)+(s^48);sc;}#undef screturn x*f;
}
int dp[maxn],pre[maxn],upd[maxn];//dp,前缀和,修改后的一些值
int f[maxn],ans[maxn];
int l[55],r[55];
int main (){int n=readint(),m=readint();for(int i=1;i<=n;i++)l[i]=readint(),r[i]=readint();for(int d=m;d>=1;d--){for(int i=0;i<=m/d;i++) dp[i]=0,pre[i]=0,upd[i]=0;pre[0]=upd[0]=1;for(int j=1;j<=m/d;j++)pre[j]=(0ll+pre[j-1]+upd[j])%mo;for(int i=1;i<=n;i++){for(int j=m/d;j>=ceil(l[i]*1.0/d);j--){if(j>r[i]/d)dp[j]=(0ll+pre[j-(int)ceil(l[i]*1.0/d)]-pre[j-r[i]/d-1]+mo)%mo;elsedp[j]=pre[j-(int)ceil(l[i]*1.0/d)];}for(int j=0;j<=m/d;j++)upd[j]=dp[j],dp[j]=0;pre[0]=upd[0];for(int j=1;j<=m/d;j++)pre[j]=(0ll+pre[j-1]+upd[j])%mo;}for(int i=0;i<=m/d;i++)f[d]=(0ll+upd[i]+f[d])%mo;ans[d]=f[d];for(int i=d+d;i<=m;i+=d)ans[d]=(0ll+ans[d]-ans[i]+mo)%mo;}printf("%d\n",ans[1]);return 0;
}

1557

A Ezzat and Two Subsequences

TP

#include<bits/stdc++.h>
using namespace std;
int main(){int t; cin>>t;while(t--){double n; cin>>n;int maxx=-0x3f3f3f3f;double sum=0;int k=n;while(k--){int x;cin>>x;sum+=x;maxx=max(x,maxx);//更新最大值}printf("%0.9lf\n",(sum-maxx)/(n-1)+maxx);}return 0;//好习惯
}

B Moamen and k-subarrays

刚开始没看到数字都不相同
TP

#include<bits/stdc++.h>
using namespace std;
int t;
int n,k;
struct node {int name,x;
}a[100005];
bool cmp(node a,node b) {return a.x<b.x;
}
int main() {cin>>t;while(t--) {cin>>n>>k;for(int i=1;i<=n;i++)cin>>a[i].x,a[i].name=i;sort(a+1,a+n+1,cmp);int cnt=1;for(int i=2;i<=n;i++)if(a[i].name!=a[i-1].name+1)cnt++;if(cnt>k)cout<<"No"<<endl;else cout<<"Yes"<<endl;}
}

C Moamen and XOR

TP
考虑到nnn为奇数时只能等于即可

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
#define int LL
const int maxn = 2e5+5;
const int mo = 1e9+7;
int readint(){int x=0,f=1;char s=getchar();#define sc (s=getchar())while(s<'0'||s>'9'){if(s=='-')f=-1;sc;}while(s>='0'&&s<='9'){x=(x<<3)+(x<<1)+(s^48);sc;}#undef screturn x*f;
}
int fac[maxn],inv[maxn];
void init(int n){fac[0]=inv[0]=inv[1]=1;for(int i=1;i<=n;i++)fac[i]=1ll*fac[i-1]*i%mo;for(int i=2;i<=n;i++)inv[i]=1ll*(mo-mo/i)*inv[mo%i]%mo;for(int i=2;i<=n;i++)inv[i]=1ll*inv[i-1]*inv[i]%mo;
}
int C(int n,int m){if(n<=0||m<=0||n<m)return 1;return 1ll*fac[n]*inv[n-m]%mo*inv[m]%mo;
}
int qkpow(int a,int b){int ans=1;while(b){if(b&1)ans=1ll*ans*a%mo;b>>=1;a=1ll*a*a%mo;}return ans%mo;
}
signed main (){init(maxn-5);int t=readint();while(t--){int n=readint(),k=readint();int sum=0,ans=0;for(int i=0;i<n;i+=2){//ijһλÏàµÈµÄ·½°¸Êý sum=(0ll+sum+C(n,i))%mo;}
//      cout<<sum<<endl;if(n&1)ans=(0ll+ans+qkpow((sum+1)%mo,k))%mo;else{for(int i=0;i<k;i++)ans=(0ll+ans+qkpow(sum,i)%mo*qkpow(qkpow(2,n),k-i-1)%mo)%mo;ans=(0ll+ans+qkpow(sum,k))%mo;}printf("%d\n",ans);}return 0;
}

1549

A Gregor and Cryptography

TP

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 2e5+5;
const int mo = 1e9+7;
int readint(){int x=0,f=1;char s=getchar();#define sc (s=getchar())while(s<'0'||s>'9'){if(s=='-')f=-1;sc;}while(s>='0'&&s<='9'){x=(x<<3)+(x<<1)+(s^48);sc;}#undef screturn x*f;
}
signed main (){int t=readint();while(t--){int p=readint();printf("%d %d\n",p/2,p/2*2);} return 0;
}

B Gregor and the Pawn Game

TP

#include<bits/stdc++.h>
using namespace std;
int t,n;
string s1,s2;
int ans1[200005],ans2[200005];
bool vis[200005];
int main(){cin>>t;while(t--){memset(vis,0,sizeof(vis));//多测不清空,保龄两行泪cin>>n;cin>>s1>>s2;int num=0;for(int i=1;i<=n;i++){ans1[i]=s1[i-1]-'0';ans2[i]=s2[i-1]-'0';}for(int i=1;i<=n;i++){if(ans1[i]==0&&!vis[i]&&ans2[i]==1){num++;vis[i]=1;}else if(i!=1&&ans1[i-1]==1&&ans1[i]==1&&!vis[i-1]&&ans2[i]==1){num++;vis[i-1]=1;//被友军走了} /*当然,第一个和最后一个因为地理原因要特殊考虑*/else if(i!=n&&ans1[i+1]==1&&ans1[i]==1&&!vis[i+1]&&ans2[i]==1){num++;vis[i+1]=1;}}cout<<num<<'\n';} return 0;
}

Web of Lies

TP
易得与周围邻居相比最小便可以留下来

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;long long n,m,t,out[200050],ans;int main(){long long i,j,u,v;cin>>n>>m;ans=n;//一开始都能活while(m--){cin>>u>>v;if(u>v) swap(u,v);if(out[u]==0) ans--;out[u]++;}cin>>t;while(t--){cin>>j;if(j==1){cin>>u>>v;if(u>v) swap(u,v);if(out[u]==0) ans--;out[u]++;}if(j==2){cin>>u>>v;if(u>v) swap(u,v);out[u]--;if(out[u]==0) ans++;}if(j==3){cout<<ans<<endl;}}return 0;
}

D Integers Have Friends

TP
设一连串的数除数为mmm,余数为bbb
有ai=ki∗m+ba_i=k_i*m+bai​=ki​∗m+b
ai+1−ai=m∗(ki+1−ki)a_{i+1}-a_i=m*(k_{i+1}-k_i)ai+1​−ai​=m∗(ki+1​−ki​)
发现差的绝对值求gcdgcdgcd便是所除的mmm
得到新的数组bi=ai+1−aib_i=a_{i+1}-a_ibi​=ai+1​−ai​,求最长区间的gcdgcdgcd大于一即可
建议写ststst表,不然容易TTT,毕竟O(n∗log2n)O(n*log^2n)O(n∗log2n)

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 2e5+5;
LL readLL(){LL x=0,f=1;char s=getchar();#define sc (s=getchar())while(s<'0'||s>'9'){if(s=='-')f=-1;sc;}while(s>='0'&&s<='9'){x=(x<<3ll)+(x<<1ll)+(s^48);sc;}#undef screturn x*f;
}
int readint(){int x=0,f=1;char s=getchar();#define sc (s=getchar())while(s<'0'||s>'9'){if(s=='-')f=-1;sc;}while(s>='0'&&s<='9'){x=(x<<3)+(x<<1)+(s^48);sc;}#undef screturn x*f;
}
LL FABS(LL x){if(x<0)x=-x;return x;
}
LL gcd(LL a,LL b){if(!b)return a;return gcd(b,a%b);
}
LL st[maxn][20],a[maxn],b[maxn];
void prepare(int n){for(int i=1;i<n;i++)st[i][0]=FABS(a[i+1]-a[i]);for(int j=1;j<=19;j++){for(int i=1;i+(1<<(j-1))-1<n;i++)st[i][j]=gcd(st[i][j-1],st[i+(1<<(j-1))][j-1]);}
}
LL query(int x,int l,int r){int k=log2(r-l+1);return gcd(st[l][k],st[r-(1<<k)+1][k]);
}
bool check(int n,int len){for(int i=1;i<=n-len+1;i++){if(query(1,i,i+len-2)>1)return 1;}return 0;
}
signed main (){int t=readint();while(t--){//      memset(tree,0,sizeof(tree));
//      memset(a,0,sizeof(a));int n=readint();for(int i=1;i<=n;i++)a[i]=readLL();if(n==1){printf("1\n");continue;}prepare(n);int l=2,r=n,ans=1;while(l<=r){int mid=(l+r)>>1;if(check(n,mid)){ans=mid;l=mid+1;}elser=mid-1;}printf("%d\n",ans);} return 0;
}

CF1555

D Say No to Palindromes

TP
可以尝试模拟一下: aaa 不回文,尝试添加一个字符,可以添加 bbb 或者 ccc, 这里选择添加 bbb, 于是字符串变成了 ababab; 再次尝试添加字符,发现只能添加 ccc,于是字符串变成了 abcabcabc; 再次尝试添加字符,发现只能添加 aaa,于是字符串变成了 abcaabcaabca;再次尝试添加字符,发现只能添加 b,于是字符串变成了 abcab;再次尝试添加字符,发现只能添加 c,于是字符串变成了 abcabcabcabcabcabc。
发现不回文的字符串只能使一个以前三个字符组成的循环,而且前三种字符只有 A33A_3^3A33​
种排列方式。
对于每次询问,可以枚举这 666 种排列方式,取最小值即可。

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
int n,m;
char a[N],s[7][3]={{'a','b','c'},{'a','c','b'},{'b','a','c'},{'b','c','a'},{'c','a','b'},{'c','b','a'}};
int sum[N][7];
int main(){scanf("%d%d",&n,&m);scanf("%s",a+1);for(int k=0;k<=6;k++){int now=0;for(int i=1;i<=n;i++,now++){if(now==3) now=0;if(a[i]!=s[k][now]) sum[i][k]++;sum[i][k]+=sum[i-1][k];}//六种情况的前缀和}for(int i=1,l,r;i<=m;i++){scanf("%d%d",&l,&r);int ans=1e9;for(int k=0;k<=6;k++){ans=min(ans,sum[r][k]-sum[l-1][k]);}//选取代价最小的那一个printf("%d\n",ans);}return 0;
}

E Boring Segments

TP
双指针维护上下界即可

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6+5;
int readint(){int x=0,f=1;char s=getchar();#define sc (s=getchar())while(s<'0'||s>'9'){if(s=='-')f=-1;sc;}while(s>='0'&&s<='9'){x=(x<<3)+(x<<1)+(s^48);sc;}#undef screturn x*f;
}
int tree[maxn<<2],lazy[maxn<<2];
struct zz{int l,r,w;
}s[maxn];
bool cmp(const zz &x,const zz &y){return x.w<y.w;
}
void pushdown(int x){if(lazy[x]!=0){lazy[x<<1]+=lazy[x];tree[x<<1]+=lazy[x];lazy[x<<1|1]+=lazy[x];tree[x<<1|1]+=lazy[x];lazy[x]=0;}
}
void update(int x,int l,int r,int goal_l,int goal_r,int val){if(goal_l<=l&&goal_r>=r){lazy[x]+=val;tree[x]+=val;return;} pushdown(x);int mid=(l+r)>>1;if(goal_l<=mid)update(x<<1,l,mid,goal_l,goal_r,val);if(goal_r>mid)update(x<<1|1,mid+1,r,goal_l,goal_r,val);tree[x]=min(tree[x<<1],tree[x<<1|1]);
}
int main (){int n=readint(),m=readint()-1;for(int i=1;i<=n;i++){s[i].l=readint(),s[i].r=readint()-1,s[i].w=readint();}sort(s+1,s+n+1,cmp);int L=0,R=0,ans=0x3f3f3f3f;while(1){while(R+1<=n&&tree[1]==0)R++,update(1,1,m,s[R].l,s[R].r,1);if(tree[1]==0)break;while(L+1<=R&&tree[1]>0)L++,update(1,1,m,s[L].l,s[L].r,-1);
//      cout<<"ans:"<<L<<" "<<R<<endl;ans=min(ans,s[R].w-s[L].w);}cout<<ans;return 0;
}

F Good Graph

TP
因为图中每个环的权值异或和为 111,所以由两个环拼成的环的异或和就是 000,不合法。因此,合法的图中每条边一定至多属于一个环。
怎么维护这个东西呢?我们只维护一颗树就好了,加入的一条边如果和树上的一条路径形成环,我们就把这条路经上的边都打上标记,在这之前要进行判断,如果边两端之间的路径上已经存在标记或形成的环的异或和不为 111,则不合法。如果新加入的边两端点本来不连通,直接加入即可。
这是一个动态维护的,显然可以用LCTLCTLCT
像我这种比较菜的就离线下来写树剖

#include <bits/stdc++.h>
using namespace std;
const int maxm = 5e5+5;
const int maxn = 3e5+5;
int readint(){int x=0,f=1;char s=getchar();#define sc (s=getchar())while(s<'0'||s>'9'){if(s=='-')f=-1;sc;}while(s>='0'&&s<='9'){x=(x<<3)+(x<<1)+(s^48);sc;}#undef screturn x*f;
}
struct dsu{int f[maxn];void makeset(int n){for(int i=1;i<=n;i++)f[i]=i;}int findset(int x){if(x!=f[x])f[x]=findset(f[x]);return f[x];}int merge(int x,int y){int fx=findset(x),fy=findset(y);if(fx==fy)return 0;f[fx]=fy;return 1;}
}a;
struct zz{int x,y,w;int type;
}s[maxm];
struct edge{int v,w,nxt;edge(){};edge(int V,int W,int N){v=V;w=W;nxt=N;}
}e[maxn<<1];
int head[maxn],edge_cnt=-1;
void addedge(int u,int v,int w){e[++edge_cnt]=edge(v,w,head[u]);head[u]=edge_cnt;e[++edge_cnt]=edge(u,w,head[v]);head[v]=edge_cnt;
}
int dep[maxn],xor_[maxn],son[maxn],siz[maxn];
int fa[maxn];
void dfs1(int u,int pre){siz[u]=1;dep[u]=dep[pre]+1;fa[u]=pre;for(int i=head[u];~i;i=e[i].nxt){int v=e[i].v;if(v==pre)continue;xor_[v]=xor_[u]^e[i].w;dfs1(v,u);siz[u]+=siz[v];if(siz[v]>siz[son[u]])son[u]=v;}
}
int dfn[maxn],rdfn[maxn],dfn_cnt,top[maxn];
void dfs2(int u,int anc){top[u]=anc;dfn[u]=++dfn_cnt;rdfn[dfn_cnt]=u;if(son[u])dfs2(son[u],anc);for(int i=head[u];~i;i=e[i].nxt){int v=e[i].v;if(v==fa[u]||v==son[u])continue;dfs2(v,v);}
}
int tree[maxn<<2],lazy[maxn<<2];
void pushdown(int x){if(lazy[x]){lazy[x<<1]=lazy[x];lazy[x<<1|1]=lazy[x];tree[x<<1]=lazy[x];tree[x<<1|1]=lazy[x];lazy[x]=0;}
}
void update(int x,int l,int r,int goal_l,int goal_r){if(goal_l<=l&&goal_r>=r){tree[x]=1;lazy[x]=1;return;} pushdown(x);int mid=(l+r)>>1;if(goal_l<=mid)update(x<<1,l,mid,goal_l,goal_r);if(goal_r>mid)update(x<<1|1,mid+1,r,goal_l,goal_r);tree[x]=max(tree[x<<1],tree[x<<1|1]);
}
int query(int x,int l,int r,int goal_l,int goal_r){if(l>=goal_l&&goal_r>=r)return tree[x];pushdown(x);int mid=(l+r)>>1,ans=0;if(goal_l<=mid)ans=max(ans,query(x<<1,l,mid,goal_l,goal_r));if(goal_r>mid)ans=max(ans,query(x<<1|1,mid+1,r,goal_l,goal_r));tree[x]=max(tree[x<<1],tree[x<<1|1]);return ans;
}
bool findcircle(int x,int y){int tx=top[x],ty=top[y];while(tx!=ty){if(dep[tx]<dep[ty])swap(x,y),swap(tx,ty);if(query(1,1,dfn_cnt,dfn[tx],dfn[x])>0)return 1;x=fa[tx];tx=top[x];}if(dep[x]>dep[y])swap(x,y);if(query(1,1,dfn_cnt,dfn[x]+1,dfn[y])>0)return 1;return 0;
}
void modify(int x,int y){int tx=top[x],ty=top[y];while(tx!=ty){if(dep[tx]<dep[ty])swap(tx,ty),swap(x,y);update(1,1,dfn_cnt,dfn[tx],dfn[x]);x=fa[tx];tx=top[x];}if(x==y)   return;if(dep[x]>dep[y])swap(x,y);update(1,1,dfn_cnt,dfn[x]+1,dfn[y]);
}
int main (){memset(head,-1,sizeof(head));int n=readint(),m=readint();for(int i=1;i<=m;i++)s[i].x=readint(),s[i].y=readint(),s[i].w=readint();a.makeset(n);for(int i=1;i<=m;i++){int u=s[i].x,v=s[i].y;if(a.merge(u,v))addedge(u,v,s[i].w),s[i].type=1;}for(int i=1;i<=n;i++){if(!dfn[i])dfs1(i,0),dfs2(i,i);}for(int i=1;i<=m;i++){if(!s[i].type){int u=s[i].x,v=s[i].y;bool flag=0;if((xor_[u]^xor_[v]^s[i].w)==0)continue;if(findcircle(u,v))flag=1;if(flag)continue;modify(u,v);s[i].type=1;}}int sum=0;for(int i=1;i<=m;i++)if(s[i].type)puts("YES");elseputs("NO");return 0;
}

CF1554

A Cherry

TP
首先,我们可以考虑设 aia_iai​为我们选的最优序列里的最大值。
接下来要确定最小值。
每次加进一个数,只能使最小值不变或者令它更小。
所以,我们考虑只加入它的相邻的一个。
也就是说,最优序列肯定是由两个相邻的数组成的。

C Mikasa

TP
由于不可能一个一个枚举,所以这道题要用到异或的一些性质。设 i∈{0,1,…,m}i\in \{0,1,\ldots ,m \}i∈{0,1,…,m},与其让 nnn 去一个一个异或 iii,不如构造一个答案,让这个答案不属于这个集合。
a⊕b=ca\oplus b=ca⊕b=c⇒a⊕c=b\Rightarrow a\oplus c=b⇒a⊕c=b
根据这个性质,为了使 n⊕i≠kn\oplus i \ne kn⊕i​=k
其实只要构造出一个 kkk,使得 n⊕k∉{0,1,…,m}n\oplus k \notin \{0,1,\ldots ,m \}n⊕k∈/​{0,1,…,m}
也就是 n⊕k≥m+1n\oplus k \ge m+1n⊕k≥m+1,接下来就是按位进行构造了。
从高位到低位一位一位构造,对于第 ii 位,我们可以分四种情况讨论:
nnn 第 iii 位为 111,(m+1)(m+1)(m+1) 第 iii 位也为 111 时,kkk 第 iii位赋为 000 就可以了,因为 1⊕0=11\oplus 0=11⊕0=1,≥m\ge m≥m 的同位。
nnn 第 iii 位为 111,(m+1)(m+1)(m+1) 第 iii 位为 0 时,k 第 iii 位赋为 000,因为 1⊕0=1,>m1\oplus 0=1,>m1⊕0=1,>m 的同位;但是 kkk 的之后所有位也都得是 000 了。为什么?因为我们构造的 k 要尽可能小。
nnn 第 iii 位为 000,(m+1)(m+1)(m+1) 第 iii 位为 111 时,kkk 第 iii 位赋为 111,因为 0⊕1=1,≥0\oplus 1=1,\ge0⊕1=1,≥ m 的同位。
nnn第 iii 位为 000,(m+1)(m+1)(m+1) 第 iii 位也为 000 时,kkk 第 iii 位赋为 000,因为 0⊕0=0,≥m0\oplus 0=0,\ge m0⊕0=0,≥m 的同位。

D Diane

TP
我们考虑一个全是同一字母的串。如果长度为奇数,那么它的各个奇数长度的子串出现次数为奇数个,偶数长度为偶数个。如果长度为偶数则刚好相反,奇数长度子串出现偶数次,偶数长度出现奇数次。
发现这个的话,之后就很简单了,就是把奇数串,偶数串都放入传中,中间加一个串防止两边影响。很容易证明这样就是对的。

CF1546D AquaMoon and Chess

仔细研究发现111111一组是可以随便移动,不受影响,所以我们可以两个111分为一组,如果连续111的个数为偶数依旧,依旧两两一组,如果发现为奇数个111那把最后的101010分为一组,令A=11,B=10A=11,B=10A=11,B=10发现ABABAB是可以随意交换的,AAA和000也是可以随便交换的,BBB和BBB就不可以(好像是一句废话,换了当没换),BBB和000也不可以换,所以BBB和000本质是一样的,相对位置不改变,所以只用统计111111的个数为aaa和000的个数为bbb,答案为(a+bb){a+b}\choose{b}(ba+b​)

CF1542C Strange Function

考虑反向定义
令F(k)F(k)F(k)为最小的不为因子为kkk的数的个数
其中2<=k<=452<=k<=452<=k<=45,因为lcm(1,2,...k)>1016lcm(1,2,...k)>10^{16}lcm(1,2,...k)>1016
显然F(k)=n/lcm(1,2...,k−1)−n/lcm(1,2....k)F(k)=n/lcm(1,2...,k-1)-n/lcm(1,2....k)F(k)=n/lcm(1,2...,k−1)−n/lcm(1,2....k)

CF1542D Priority Queue

考虑的每个数单独求贡献,于是可以在+x+\ \ \ \ x+    x对这个数单独进行dpdpdp求他一共有多少种方案
dp[i][j]dp[i][j]dp[i][j]表示前iii个操作已经处理,总共有jjj个数比xxx小,因为比他小的数比他先删除
pospospos为我们研究的+x+\ \ \ \ x+    x为第几次操作
考虑i<posi<posi<pos的情况
若当前这一位是−-−号,那么就有 dpi,j=dpi−1,j+dpi−1,j+1dp_{i,j}=dp_{i-1,j}+dp_{i-1,j+1}dpi,j​=dpi−1,j​+dpi−1,j+1​,另外特别注意一下 dpi,0dp_{i,0}dpi,0​需要再次 +dpi−1,0+ dp_{i-1,0}+dpi−1,0​
不选这个−-−号,不变,选了这个−-−号并且 jjj 本来就已经是 000 了,也是不变,因此 dpi−1,0dp_{i-1,0}dpi−1,0​要算两遍)
如果是+++号,并且当前的 valj>valposval_{j}>val_{pos}valj​>valpos​
那么选不选都无所谓,就有 dpi,j=dpi−1,j∗2dp_{i,j}=dp_{i-1,j}*2dpi,j​=dpi−1,j​∗2
否则的话,如果选,jjj就增加 111,否则不变,就有dpi,j=dpi−1,j+dpi−1,j−1dp_{i,j}=dp_{i-1,j}+dp_{i-1,j-1}dpi,j​=dpi−1,j​+dpi−1,j−1​
考虑i>posi>posi>pos的情况
若当前这一位是−-−号, dpi,0dp_{i,0}dpi,0​不需要再次 +dpi−1,0+ dp_{i-1,0}+dpi−1,0​,因为这样就会把valposval_{pos}valpos​给删掉
其次为+++且可选可不选的的一定要满足valpos≤valjval_{pos}\le val_{j}valpos​≤valj​,不然方案重复等死了

#include <bits/stdc++.h>
using namespace std;
const int maxn = 505;
const int mo = 998244353;
int readint(){int x=0,f=1;char s=getchar();#define sc (s=getchar())while(s<'0'||s>'9'){if(s=='-')f=-1;sc;}while(s>='0'&&s<='9'){x=(x<<3)+(x<<1)+(s^48);sc;}#undef screturn x*f;
}
int a[maxn],dp[maxn][maxn];
int ans;
void getdp(int x,int n){for(int i=0;i<=n+1;i++)for(int j=0;j<=n+1;j++)dp[i][j]=0;dp[0][0]=1;for(int i=1;i<x;i++)if(a[i]==0){for(int j=0;j<=n;j++)dp[i][j]=(0ll+dp[i-1][j]+dp[i-1][j+1])%mo;dp[i][0]=(0ll+dp[i][0]+dp[i-1][0])%mo;}else{for(int j=0;j<=n;j++){if(a[i]>a[x])dp[i][j]=1ll*dp[i-1][j]*2%mo;elsedp[i][j]=(0ll+dp[i-1][j]+dp[i-1][j-1])%mo;}}for(int j=0;j<=n;j++)dp[x][j]=dp[x-1][j];for(int i=x+1;i<=n;i++){if(a[i]==0){for(int j=0;j<=n;j++)dp[i][j]=(0ll+dp[i-1][j]+dp[i-1][j+1])%mo;}else{for(int j=0;j<=n;j++){if(a[i]>=a[x])dp[i][j]=1ll*dp[i-1][j]*2%mo;elsedp[i][j]=(0ll+dp[i-1][j]+dp[i-1][j-1])%mo;}}}int sum=0;for(int j=0;j<=n;j++)sum=(0ll+sum+dp[n][j])%mo;ans=(0ll+ans+1ll*sum*a[x]%mo)%mo;
}
int main (){int n=readint();for(int i=1;i<=n;i++){char op[3];scanf("%s",op);if(op[0]=='-')continue;a[i]=readint();}for(int i=1;i<=n;i++){if(a[i]!=0)getdp(i,n);}cout<<ans<<endl;return 0;
}

CF杂题训练(交互题不做,2500以上的看情况吧)相关推荐

  1. AtCoder 杂题训练

    前言: 因为要普及了,今年没一等就可以退役去学文化课了,所以暑假把历年noip普及组都刷了一遍,离noip还有50+天,想弄点强化训练什么的. 想了想,就这些天学文化课之余有空就把AtCoder之前那 ...

  2. 逻辑思维训练500题(带答案)前237题 文末附完整版PDF

    第一章 假设法 一个真实的假设往往可以让事实呈现眼前,让真理浮出水面.一个人如果做什么事都可以让其思维以这些假设前提为基础,那么他便能真真正正地活在NLP里而不会陷入困境,他的人生也就会有更大地进步和 ...

  3. BUCTOJ - 2023上半年ACM蓝桥杯每周训练题-1-A~K题C++Python双语版

    文章目录 BUCTOJ - 2023上半年ACM&蓝桥杯每周训练题-1-A~K题C++Python双语版 前言 问题 A: 1.2 神奇兔子数列 题目描述 输入 输出 解题思路 AC代码 C+ ...

  4. ACM思维题训练 Section A

    题目地址: 选题为入门的Codeforce div2/div1的C题和D题. 题解: A:CF思维联系–CodeForces -214C (拓扑排序+思维+贪心) B:CF–思维练习-- CodeFo ...

  5. Strange Shuffle CodeForces - 1471E(交互题)

    交互题 这类型不同于普通的题. 可以理解为有个问题需要你解决,你通过输入某些东西表示你要问系统的问题,这时系统会回答你的问题.在代码中的回答方式就是会输入某个东西就是系统给你的答案,通过这些信息你可以 ...

  6. 逻辑思维训练1200题-蓝桥杯计算思维参考

    黑格尔曾说过,逻辑是一切思考的基础.逻辑思维能力强的人能迅速.准确地把握住问题的实质,面对纷繁复杂的事情能更容易找到解决的办法. <逻辑思维训练1200 题>介绍了排除法.递推法.倒推法. ...

  7. PTA寒假基础题训练(含解题思路)(下)

    目录 7-36 字符串的冒泡排序 AC代码: 7-37 龟兔赛跑 AC代码: 7-38 N个数求和 AC代码: 7-39 数列求和-加强版 AC代码: 7-40 抓老鼠啊~亏了还是赚了? AC代码: ...

  8. PTA寒假基础题训练(含解题思路)(中)

    目录 7-19 两个有序单链表求差集 AC代码: 7-20 统计数字字符和空格 AC代码: 7-21 打印沙漏 AC代码: 7-22 Wifi密码 AC代码: 7-23 福到了 AC代码: 7-24 ...

  9. CF1039B:交互题+二分

    CF1039B 题解: 第二次做交互题,对交互题没什么感觉.你要询问系统,所以你cout输入,系统再立刻给你cin答案.交互题格式就在于要清空缓存区,可以在printf输出完之后,加一fflush(s ...

最新文章

  1. sqlserver如何通过管理器设置字段的自增
  2. matlab滤波仿真
  3. write/read/send/receive函数比较
  4. [文摘20090203]手机基本知识
  5. stub 和 skeleton 的讲解,自己实现一个stub和skeleton程序
  6. 理解Android Binder机制原理
  7. vue动态监听窗口高度 - 全背景banner
  8. 【Android】HorizontalScrollView内子控件横向拖拽
  9. android读写串口
  10. 玲珑学院 1138 - 震惊,99%+的中国人都会算错的问题
  11. ApplicationContext.xml配置文件
  12. eclipse Android开发——布局查看
  13. Cuda Graph (cuda 优化)
  14. 论文分享|高精度面结构光三维测量方法研究
  15. MySQL主从复制与读写分离
  16. 凸优化之共轭函数(一)
  17. Mysql出现问题:ERROR 1062 (23000): Duplicate entry ‘‘ for key ‘PRIMARY‘解决方案
  18. 关于jupyer中,文件夹所在位置如何查询
  19. Java虚拟机字节码指令
  20. 百度地图InfoWindow事件绑定

热门文章

  1. const int a = 100; 这种引用虽然可以, 但要少用或者不用
  2. 当CNN遇见Transformer!华为诺亚提出CMT:新视觉Backbone
  3. 密码学:流加密法与块加密法
  4. Minecraft 1.16.5模组开发(五十) 书籍词典 (Guide Book)
  5. FPGA如何利用查表法得到某角度所对应的正弦值、余弦值
  6. python多进程爬取上海房价并画出热力图分析
  7. STM32的SWD调试方式
  8. 天天影院在线购票平台的实现(SSM)
  9. 网络空间技能大赛A模块(乱)
  10. 有赞云开发小坑(个人笔记)