Educational Codeforces Round 132 (Rated for Div. 2)(补题中)
作者:互联网
加粗:赛时AC
普通:赛后AC
A. Three Doors
水题,但我一开始没看懂题意,就随便猜了个题意。反正就是拿着钥匙开一扇门,门后有别的钥匙,问你能不能全打开。
int main() { read(t); while(t--) { int x; read(x); memset(buc,0,sizeof(buc)); for(int i=1;i<=3;i++) read(a[i]); buc[x]=1; buc[a[x]]=1; buc[a[a[x]]]=1; //buc[a[a[a[x]]]]=1; bool flag=1; for(int i=1;i<=3;i++) if(buc[i]==0) flag=0; if(!flag) printf("NO\n"); else printf("YES\n"); } return 0; }View Code
B. Also Try Minecraft
依然没有完全看懂题意,但是模拟了一下样例,就是一个前缀和后缀和的问题,统计之间的差值。
int main() { read(n);read(m); for(int i=1;i<=n;i++) read(a[i]); for(int i=1;i<=n;i++) { if(a[i]>a[i+1]) p[i]=p[i-1]+(a[i]-a[i+1]); else p[i]=p[i-1]; } for(int i=n;i>=1;i--) { if(a[i]>a[i-1]) rp[i]=rp[i+1]+(a[i]-a[i-1]); else rp[i]=rp[i+1]; } for(int i=1;i<=m;i++) { ll x,y; read(x);read(y); if(x<y) printf("%lld\n",p[y-1]-p[x-1]); else printf("%lld\n",rp[y+1]-rp[x+1]); } return 0; }View Code
C. Recover an RBS
关于括号匹配,要遵循两个要点,一是一定要保证每个位置的左括号前缀和大于右括号的,第二点是最终左右括号个数相等。
这题我是这样考虑的。
题目给了一个很重要的条件,就是保证了必定存在至少一种情况符合匹配的模式串,那么如果答案唯一,应该是哪一种?
我们将左括号看做+1,右括号看做-1,那么两个要点就变为了任何地方的前缀和大于1并且最终前缀和为0。
显然,对于所有的?,我们可以根据左括号和等于右括号和,算出这当中有多少左右括号,然后将在前面等量的?换为需要的(,在后面的换为),这必定是一种可行的情况。
然后计算这个序列的前缀和,如果我们要变换我们填上的括号的方向,一定是将一组()变为)(,此时在这之中的所有前缀和都要-2,如果有负数,就不能变换。
显然我们应该变换位于中间的一组问号变得括号,此时削减的前缀和最少并且与其他的括号组合是被包含的关系。
int main() { read(T); while(T--) { a=0;b=0; cin>>s; int len=s.size(); for(int i=0;i<len;i++) { p[i]=0; if(s[i]=='(') a++; else if(s[i]==')') b++; } a=len/2-a;b=len/2-b; bool flag=0; int las=0; for(int i=0;i<len;i++) { p[0]=1; if(s[i]=='?') { if(a) {a--;if(i!=0)p[i]=p[i-1]+1;if(a==0) las=i;} else {b--;p[i]=p[i-1]-1;} } else if(s[i]=='(') p[i]=p[i-1]+1; else p[i]=p[i-1]-1; } for(int i=las;i<len;i++) { if(s[i]=='?'&&i!=las) break; if(p[i]<2) flag=1; } if(!flag) printf("NO\n"); else printf("YES\n"); } return 0; }View Code
队友给了我一个别的思路,代码更加简洁一些,但是中心思想还是两个要点:
从左到右运行的时候,设置两个计数变量num1和num2,遇到'(',num1++,遇到')',num1--,遇到'?',num2++。
遇到对于第i位,如果此时num1+num2==1,意味着此时剩下的)比?个数小1,在那么显然为了满足括号匹配条件1,所有的问号应该都是右括号,我们就可以将这一部分的计数重置为num1=1,num2=0,意味着前i项的?是固定不变的。
运行到最后,如果剩下的'('或者')'数量和'?'数量一致,那么?是固定不变的,否则括号的数量会小于问号数量,意味着问号是可以变方向的。
void solve() { cin >> s + 1; int n = strlen(s + 1); int wh = 0, cnt = 0; rep(i, 1, n) { if (s[i] == '(') wh++; else if (s[i] == ')') wh--; else cnt++; if (wh + cnt == 1) wh = 1, cnt = 0; } if (abs(wh) == cnt) cout << "YES\n"; else cout << "NO\n"; }View Code
D. Rorororobot
这题反而比上题思路清晰点。
题目给出的障碍物是挨着地面的,然后行动的参数是每次都行动k格。
那么我们首先要确定没有障碍物的情况下能否到达,机器人智能走上下左右四个方向,那么起点终点的坐标对k取模一定要相等。
其次由于不要求我们最低的步数,我们每次都可以将机器人升到最高的位置去跨越这些障碍,到达终点的上方,这就需要我们算出起始列到终点列的最高障碍物,可以用ST表进行维护。
注意哪个是横坐标,那个是纵坐标。。。
inline void ycl() { for(int i=1;i<=18;i++) { for(int j=1;j+(1<<i)-1<=m;j++) { st[i][j]=max(st[i-1][j],st[i-1][j+(1<<(i-1))]); } } } inline ll search1(ll l,ll r) { ll len=(ll)log2(r-l+1); return max(st[len][l],st[len][r-(1<<len)+1]); } int main() { read(n);read(m); for(int i=1;i<=m;i++) read(a[i]),st[0][i]=a[i]; ycl(); read(Q); while(Q--) { ll x,y,xx,yy,k; read(x);read(y); read(xx);read(yy); read(k); if(xx%k!=x%k||yy%k!=y%k) cout<<"NO"<<endl; else { ll maxx=search1(min(y,yy),max(y,yy)); ll maxm=max(x,(x%k)+n/k*k); if(maxm>n) maxm-=k; if(maxm<=maxx) cout<<"NO"<<endl; else cout<<"YES"<<endl; } } return 0; }View Code
标签:Educational,Rated,前缀,int,wh,括号,read,补题,-- 来源: https://www.cnblogs.com/ztlsw/p/16514929.html