Educational Codeforces Round 153 A~E
Educational Codeforces Round 153
A-Not a Substring
题意:给出一个长为
判断是否有解,若有解,给出一个合法括号序列。
显然,我们先判掉原序列为 "()" 的情况,一个合法括号序列必然要出现该图形。
其次,容易发现,对于存在 "((" 或者 "))" 连续段的,则 "()()()……" 此类必然是一个解。
如果不存在,则显然 ((((())))) 此类是一个解。
B-Fancy Coins
题意:你有
现在需要买一个价值为
首先,我们需要将
然后,我们将
int n,k,a1,ak;
cin>>n>>k>>a1>>ak;
int ans=0;
if(a1>=n%k)a1-=n%k,n-=n%k;
else ans+=n%k-a1,a1=0,n-=n%k;
int s=n/k;
if(s<=ak+a1/k)cout<<ans<<"\n";
else{
int t=a1/k;ak+=t;
ans+=s-ak;
cout<<ans<<"\n";
}
C-Game on Permutation
题意:有两个人轮流操作。最初有一个序列
有一个筹码,最初由先手任意放在一个位置上,接着后/先手交替移动,每一次可以将筹码从
当一个棋子不可以移动时,当前轮到的人获胜。
对于博弈论问题,我们考虑必胜态与必败态。
必败态是什么?也即后手可以通过移动一次筹码将其移动到一个能且仅能移动再一次的位置上。
那么必胜态?也即这个位置满足无论后手如何移动,它都只能移动到一个再不能移动的位置。
我们先考虑不可移动的位置
然后考虑如何维护再不能移动的位置。
显然,我们可以通过权值树状数组维护当前节点
当这二者相等且不为0的时候,说明当前节点是一个必胜点。
read(n);
for(int i=1;i<=n;i++){
read(a[i]);c[i]=b[i]=d[i]=0;
}
int mn=n,ans=0;
for(int i=1;i<=n;i++){
mn=min(mn,a[i]);
if(mn==a[i])b[i]=1;
}
for(int i=1;i<=n;i++){
if(ask(a[i])==ask2(a[i])&&ask(a[i])!=0)++ans;
add(a[i],b[i]);add2(a[i],1);
}
cout<<ans<<"\n";
D-Balanced String
题意:给定一个01序列
每一次可以交换任意两个数,求使得
启发:可以确定的信息尽量确定。
首先我们可以统计出
所以,我们让
现在我们想想,假设我们已经知道了
所以容易知道,本质上是让
关于这种问题,是容易解决的。设
则显然有
不过空间需要滚动一下。
int main(){
cin>>b+1;n=strlen(b+1);
for(int i=1;i<=n;i++)a[i]=b[i]-'0',c1+=a[i];
c0=n-c1;int cnt=n*(n-1)/2-c0*(c0-1)/2+c1*(c1-1)/2;cnt/=2;cnt+=c1;
memset(f,0x3f,sizeof f);
f[0][0][0]=0;
for(int i=1;i<=n;i++){
for(int j=0;j<=min(c1,i);j++){
for(int k=0;k<=cnt;k++){
f[i&1][j][k]=min(f[i&1][j][k],f[(i^1)&1][j][k]);
if(k>=i&&j)f[i&1][j][k]=min(f[i&1][j][k],f[(i^1)&1][j-1][k-i]+(a[i]==0));
}
}
}
cout<<f[n&1][c1][cnt]<<"\n";
}
E-Fast Travel Text Editor
题意:给定一个长为
光标移动的规则如下:
每一次移动,从下列三种方案中选择一个:
- 从
移动到 ,前提是 - 从
移动到 ,前提是 - 从
移动到 ,满足
现给出若干询问,每次给出
这个题,很明显是个最短路题,但怎么搞最短路是最重要的。
注意到求
- 直接暴力移动,答案
- 找到一对传送点
,两边自己处理。
有一个直接的想法是对于
然后对于正常移动,边权为2。最后将答案除2即可解决问题。但这样问题就化为了一个全源最短路问题,强行跑dijkstra也是必TLE。
那么有没有更高效的做法?
注意到在本题中,操作可逆,那么我们换个方向,何不考虑组合答案?
我们的起点并不需要将
我们仅仅需要将每一个新建的虚点作为起点跑最短路即可。甚至在这里,我们不需要建图,直接BFS求最短路。但需要注意的是,这里不需要建立出虚点,但需要标记虚点是否走过。(否则会出现某个虚点连很多条边的情况,导致vis判太多次超时)
int main(){
ios::sync_with_stdio(false);
cin>>a+1;n=strlen(a+1);
cin>>m;memset(dis,-1,sizeof dis);
for(int i=1;i<n;i++)p[a[i]-'a'][a[i+1]-'a'].push_back(i);
for(int i=0;i<26;i++){
for(int j=0;j<26;j++){
if(p[i][j].empty())continue;
for(int s=0;s<26;s++)for(int t=0;t<26;++t)vis[s][t]=0;
queue<int>q;
for(auto x:p[i][j]){
dis[i][j][x]=0;q.push(x);
}
while(!q.empty()){
int x=q.front();q.pop();
if(x>1&&dis[i][j][x-1]==-1){
dis[i][j][x-1]=dis[i][j][x]+1;
q.push(x-1);
}
if(x<n-1&&dis[i][j][x+1]==-1){
dis[i][j][x+1]=dis[i][j][x]+1;
q.push(x+1);
}
if(vis[a[x]-'a'][a[x+1]-'a'])continue;
vis[a[x]-'a'][a[x+1]-'a']=1;
for(auto k:p[a[x]-'a'][a[x+1]-'a']){
if(dis[i][j][k]==-1){
dis[i][j][k]=dis[i][j][x]+1;
q.push(k);
}
}
}
}
}
while(m--){
int x,y;cin>>x>>y;
int ans=abs(x-y);
for(int i=0;i<26;i++)for(int j=0;j<26;j++)if(!p[i][j].empty())ans=min(ans,dis[i][j][x]+dis[i][j][y]+1);
cout<<ans<<"\n";
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!