Codeforces Round #707(Div.2)(A~B)
……又是两题滚粗……orz(人生重来算了)(不过好像based on Moscow Open Olympiad in Informatics,所以变难了不少(挠头),所以肯定不是我的问题)
A.Alexey and Train
本题是一道模拟题。首先各车站之间所需要的时间是不变的,a[i]-b[i-1]。然后在加上tmi就是这一段的路程。
因此我们先计算好原本的时间即a[i]-b[i-1]。然后再通过修改b[]即离站时间即可。注意要保证至少需要停留的时间。
AC代码如下:
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<queue> #include<vector> #define MAXN 105 using namespace std; typedef pair<int,int> pii; int t,n,tm[MAXN],ans; struct sta{ int a,b,lastt; }s[MAXN]; int main(){ scanf("%d",&t); s[0].b=0; while(t--){ ans=0; scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d%d",&s[i].a,&s[i].b); s[i].lastt=(s[i].b-s[i].a)/2 + ((s[i].b-s[i].a)%2); s[i].a-=s[i-1].b; } for(int i=1;i<=n;i++) scanf("%d",&tm[i]); for(int i=1;i<=n;i++){ ans=s[i].a+s[i-1].b+tm[i];//ans为到第i个站点的时间 if(ans+s[i].lastt>s[i].b) s[i].b=ans+s[i].lastt;//更新离开时间 // printf("经过%d站点,车到达时间为%d,离开时间为%d,持续时间为%d\n",i,s[i].a,s[i].b,s[i].lastt); } printf("%d\n",ans); } }
B.Napoleon Cake
这题我一开始直接暴力。从1~n遍历a数组然后对每个a数组至上向下涂色。(当然t了)
然后我们思考一下。这个过程重复的就是已经涂过色的部分还要再涂一遍。
这时候我想到了前几天刚学的KMP算法。(虽然好像做麻烦了qwq,看到大佬的题解好像可以直接用差分做)
建了一个next数组。在至上向下涂色的过程中,如果遇到已经涂色的块了,就next到他的下一个未涂色块中。如果a能支撑到那里的话就涂色
AC代码如下:
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<queue> #include<vector> #define MAXN 200005 using namespace std; typedef pair<int,int> pii; int t,n,a[MAXN],vis[MAXN],next1[MAXN]; int find_next(int x,int temppp=0){//temppp若无传参,则默认为0,不影响 if(x==0){ for(int i=temppp;i>0;i--) next1[i]=0; } int temp=x; while(vis[temp]) temp=next1[temp]; next1[x]=temp; return temp; } int main(){ scanf("%d",&t); next1[0]=0; while(t--){ memset(vis,0,sizeof(vis)); scanf("%d",&n); for(int i=1;i<=n;i++) next1[i]=i-1;//初始化,下一个不是0的就是自己的下一块 for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<=n;i++){ if(!a[i]) continue; int temp=1; while(temp<=a[i]){ if(vis[i-temp+1]){//如果这一块已经涂过了 int nexttemp=find_next(i-temp+1);//找下一个没涂过的 if(!nexttemp)//如果没了 break; else temp+=(i-temp+1-nexttemp);//如果还有。这样不仅修改了下标,还修改了涂色次数。 }else{ vis[i-temp+1]=1; if(i-temp==0){ find_next(0,i);//全部涂完。已有的块全部指向0,表示下面没有了。 break; } if(temp==a[i]){ next1[i]=find_next(i);//记录最上面的一个已经涂色的。 } temp++; } } } for(int i=1;i<=n;i++) printf("%d ",vis[i]); printf("\n"); } }

浙公网安备 33010602011771号