Codeforces Round #504 (rated, Div. 1 + Div. 2, based on VK Cup 2018 Final)
A:
//By SiriusRen #include <bits/stdc++.h> using namespace std; int n,m; char a1[200050],a2[200050]; void solve(int x){ for(int i=1;i<=x-1;i++)if(a1[i]!=a2[i]){ puts("NO");exit(0); } int j=m; for(int i=n;i>=x+1;i--){ if(a1[i]!=a2[j--]){ puts("NO");exit(0); } } } int main(){ scanf("%d%d",&n,&m); if(n>m+1){puts("NO");return 0;} scanf("%s%s",a1+1,a2+1); for(int i=1;i<=n;i++)if(a1[i]=='*'){ solve(i),puts("YES");return 0; } if(n!=m){ puts("NO");return 0; }solve(n+1); puts("YES"); }
B:
给你两个数n和k,问有多少对(a,b) a<=n,b<=n,a≠b,使得a+b=k
//By SiriusRen #include <bits/stdc++.h> using namespace std; long long n,k; int main(){ scanf("%lld%lld",&n,&k); if(n*2<k)printf("0\n"); else if(k<=n)printf("%lld\n",(k-1)/2); else{ long long tmp=k-n; printf("%lld\n",(n-tmp+1)/2); } }
C:
给你一个括号序列,让你删点儿东西,变成长度为m的合法括号序列
//By SiriusRen #include <bits/stdc++.h> using namespace std; int n,m,top; char s[200050],stk[200050]; int main(){ scanf("%d%d",&n,&m); m=(n-m)/2; scanf("%s",s+1); for(int i=1;i<=n;i++){ if(s[i]=='(')stk[++top]=s[i]; else{ if(m)--top,--m; else stk[++top]=s[i]; } } for(int i=1;i<=top;i++)putchar(stk[i]);puts(""); }
D:
对于一个长度n的数组进行q次查询,i从1到q,第i次将任意一段连续的部分全部染成i。
最后得到的数组中可能会存在“污点”0.即最后对数组的任意子集set为0.
给出n和q,以及带污点的长为n的数组,判断是否能将其还原成没有0的合理数组。
如果可以则输出任意一合理数组。
思路:
首先,一个同样的数中间不可能夹着比它小的数。
为了保证q必须出现,需要特判
也就是线段树区间置一,区间求和
(我是怎么交了10遍才过的,,,)
//By SiriusRen #include <bits/stdc++.h> using namespace std; const int N=200500; int n,q,a[N],lazy[N<<3],tree[N<<3],lsti,maxx; vector<int>vec[N]; void push_down(int l,int r,int pos){ int mid=(l+r)>>1,lson=pos<<1,rson=pos<<1|1; lazy[pos]=0,lazy[lson]=1,lazy[rson]=1; tree[lson]=mid-l+1,tree[rson]=r-mid; } int query(int l,int r,int pos,int L,int R){ if(lazy[pos])push_down(l,r,pos); if(l>=L&&r<=R){return tree[pos];} int mid=(l+r)>>1,lson=pos<<1,rson=pos<<1|1; if(mid<L)return query(mid+1,r,rson,L,R); else if(mid>=R)return query(l,mid,lson,L,R); else return query(l,mid,lson,L,R)+query(mid+1,r,rson,L,R); } void insert(int l,int r,int pos,int L,int R){ if(lazy[pos])push_down(l,r,pos); if(l>=L&&r<=R){lazy[pos]=1;tree[pos]=r-l+1;return;} int mid=(l+r)>>1,lson=pos<<1,rson=pos<<1|1; if(mid<L)insert(mid+1,r,rson,L,R); else if(mid>=R)insert(l,mid,lson,L,R); else insert(l,mid,lson,L,R),insert(mid+1,r,rson,L,R); tree[pos]=tree[lson]+tree[rson]; } int main(){ scanf("%d%d",&n,&q); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); vec[a[i]].push_back(i); if(!a[i])lsti=i,insert(1,n,1,i,i); maxx=max(maxx,a[i]); } if(maxx!=q&&(!lsti)){puts("NO");return 0;} for(int i=0;i<=q;i++)sort(vec[i].begin(),vec[i].end()); for(int i=q;i;i--){ int tmp=vec[i].size(); if(!tmp)continue; int bgn=vec[i][0],end=vec[i][vec[i].size()-1]; if(end-bgn+1<tmp+query(1,n,1,bgn,end)){puts("NO");return 0;} insert(1,n,1,bgn,end); } for(int i=1;i<=n;i++){ if(a[i])break; a[i]=1; } for(int i=1;i<=n;i++)if(!a[i])a[i]=a[i-1]; if(maxx!=q&&lsti)a[lsti]=q; puts("YES"); for(int i=1;i<=n;i++)printf("%d ",a[i]); }
E:
构造题
给一个n*n的矩阵,中间有障碍,你可以询问(x1,y1),(x2,y2)表示从(x1,y1)能不能到(x2,y2)
其中,两个点的曼哈顿距离>=n
从(1,1)不断向右下挪
当曼哈顿距离==n的时候
把(n,n)向左上挪
#include <string> #include <iostream> using namespace std; int n; bool vis[1005][1005]; bool query(int x, int y) { if (x + y <= n + 1) cout << "? " << x << " " << y << " " << n << " " << n << endl; else cout << "? " << 1 << " " << 1 << " " << x << " " << y << endl; cout.flush(); string s; cin >> s; return s[0] == 'Y'; } void search1(int x, int y) { vis[x][y] = true; if (x + y == n + 1) return; if (query(x, y + 1)) search1(x, y + 1); else search1(x + 1, y); } void search2(int x, int y) { vis[x][y] = true; if (x + y == n + 1) return; if (query(x - 1, y)) search2(x - 1, y); else search2(x, y - 1); } void putanswer() { cout << "! "; int x = 1, y = 1; while (x != n || y != n) { if (vis[x][y + 1]) { cout << "R"; y = y + 1; } else if (vis[x + 1][y]) { cout << "D"; x = x + 1; } } cout << endl; cout.flush(); } int main() { cin >> n; search1(1, 1); search2(n, n); putanswer(); return 0; }