codeforces 859 div4
A
题目

签到题,没有算法,纯if判断然后输出
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| #include <bits/stdc++.h> using namespace std;
int t,a,b,c;
int main(void){ ios::sync_with_stdio(false); cin.tie(0);cout.tie(0); cin >> t; for(int i=0;i<t;i++){ cin >> a >> b >> c; if(a+b == c) cout << "+" <<'\n'; else cout << "-" <<'\n'; } return 0; }
|
B
题目

此题贪心,题目简述就是偶数之和大于级数之和就行,难度也是签到的难度
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| #include <bits/stdc++.h> using namespace std;
int ou=0,ji=0,a,t,n; int main(void){ ios::sync_with_stdio(false); cin.tie(0);cout.tie(0); cin >> t; for(int i=0;i<t;i++){ cin >>n; for(int j=0;j<n;j++){ cin >>a; if(a%2==0) ou +=a; else ji += a; } if(ou>ji) cout<<"YES"<<'\n'; else cout << "No"<<'\n'; ji=0;ou=0; } return 0; }
|
C
题目

模拟题,字符串处理。此题题意是给你一串字符串,你可以把同种的所有字母都用1或0来代替,问你能不能形成像0101010这种1和0交替出现的形式。用Hash数组来记录字符串中某个字母是否已经被替换,然后判断就行
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| #include <bits/stdc++.h> using namespace std;
string s; char cha; int t,n,Hash[101][2001],pd;
int main(void){ ios::sync_with_stdio(false); cin.tie(0);cout.tie(0); cin >>t; for(int i=0;i<t;i++){ cin >> n;cin>>s; fill_n(&Hash[0][0],101*2001,-1); for(int j=0;j<n;j++){ if(Hash[t][j] != -1) continue; if(j!=n-1 && s[j]==s[j+1]){ pd=1;break; } else{ cha =s[j]; Hash[t][j]=j%2; s[j]='0'; auto it =s.find(cha); while(it != string::npos){ Hash[t][it]=j%2; s[it]='0'; it = s.find(cha); } } } for(int j=0;j<n-1;j++){ if(Hash[t][j] == Hash[t][j+1]){ pd=1;break; } } if(pd==0) cout << "YES" <<endl; else cout << "NO" << endl; pd=0; } return 0; }
|
D
题目

此题题意为给你一个整数数组,把其中a[left]到a[right]都替换为k,问你数组元素之和是否为奇数。我第一遍直接暴力速度解决,结果TLE,发现n和q数据太大了,明显不是让我暴力的。因此改用前缀和解决
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| #include <bits/stdc++.h> using namespace std;
long long t,n,q,l,r,k,a[200001],cache,sum=0;
int main(void){ ios::sync_with_stdio(false); cin.tie(0);cout.tie(0); cin >> t; for(int i=0;i<t;i++){ cin >> n >> q; for(int j=0;j<n;j++){ cin >> cache; a[j] = cache; } for(int j=1;j<n;j++) a[j]+=a[j-1]; for(int j=0;j<q;j++){ cin >> l >> r >> k; if(l>1) sum = a[l-2] + a[n-1]-a[r-1] + (r-l+1)*k; else sum = a[n-1]-a[r-1] + (r-l+1)*k; if(sum %2 ==1) cout << "YES" <<'\n'; else cout << "NO" << '\n'; sum=0; } } return 0; }
|
E
题目

题干非常长,快有我长了,有点像猜数字的升级版,主要用二分来做
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| #include <bits/stdc++.h> using namespace std;
int t,n,a[200001],ai,weight=0,weight_in,special,inter,l,r,left=1;
int main(void){ ios::sync_with_stdio(false); cin.tie(0);cout.tie(0); cin >> t; while(t--){ cin>>n; for(int i=0;i<n;i++){ cin>>ai; a[i]=ai; } l=1;r=(l+n)/2;weight=0; while(1){ cout<<"?"<<' '<<r-l+1<<' '; for(int i=l;i<=r;i++){ cout<<i<<' '; weight+=a[i-1]; }cout<<endl; cin >> weight_in; if(weight!=weight_in && r==l ){ special=l;break; } if(weight == weight_in) { if(l+1==n){ special=n;break; } if(r+1<=n) l=r+1; else l=r; r=(l+n)/2; }else{ n=r; r=(l+r)/2; } weight=0; } cout<<"!"<<' '<<special<<endl; } return 0; }
|
F
题目

这道是这套里最难的题,主要是dfs,一个小球沿着斜线一直跑,碰到墙就转向,碰到墙角就反弹,问你能不能经过某一点。这题的行和列最大都为25000,如果直接room[25000][25000],那么25000250004/1024/1024/1024=2.3GB 会爆栈,改用单独的行和列变量来判断。
初始思路:用dfs双头搜,两次搜索都是碰到墙角就结束,因为两个墙角构成一个死循环,同时判断不撞墙角的死循环的特殊情况,构成四边形死循环也结束。这个思路没有全部AC,从下午调到第二天下午,恼火,然后换了个思路。
AC思路:一个格子有四个方向,一共有nm个格子,所以小球至多走nm*4步,如果超过这个数必然是死循环,结束。

代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
| #include <bits/stdc++.h> using namespace std;
int pd = 0, times = 0, room, t, n, m, i1, j_1, i2, j2; string d; struct zb { int x; int y; bool operator==(const zb& other) const { return x == other.x && y == other.y; } }Next; map <string, zb> direction; #define checkx (Next.x>0 && Next.x<=n) #define checky (Next.y>0 && Next.y<=m) #define qiangjiao (Next.x<1 && Next.y<1 || Next.x<1 && Next.y>m || Next.x>n && Next.y<1 || Next.x>n && Next.y>m) void dfs(int dx, int dy, string& d, int& times) { if (dx == i2 && dy == j2) { pd = 1; return; } Next.x = dx + direction[d].x; Next.y = dy + direction[d].y; if (times>room) return; if (qiangjiao) { times++; if (d == "UL") { d = "DR"; Next.x = dx; Next.y = dy; } else if (d == "UR") { d = "DL"; Next.x = dx; Next.y = dy; } else if (d == "DR") { d = "UL"; Next.x = dx; Next.y = dy; } else if (d == "DL") { d = "UR"; Next.x = dx; Next.y = dy; } } else if (Next.x < 1 && checky) { times++; if (d == "UL") { d = "DL"; Next.x = dx; Next.y = dy; } if (d == "UR") { d = "DR"; Next.x = dx; Next.y = dy; } } else if (Next.x > n && checky) { times++; if (d == "DR") { d = "UR"; Next.x = dx; Next.y = dy; } if (d == "DL") { d = "UL"; Next.x = dx; Next.y = dy; } } else if (checkx && Next.y < 1) { times++; if (d == "UL") { d = "UR"; Next.x = dx; Next.y = dy; } if (d == "DL") { d = "DR"; Next.x = dx; Next.y = dy; } } else if (checkx && Next.y > m) { times++; if (d == "UR") { d = "UL"; Next.x = dx; Next.y = dy; } if (d == "DR") { d = "DL"; Next.x = dx; Next.y = dy; } } dfs(Next.x, Next.y, d, times); } int main(void) { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); direction["UL"] = { -1,-1 }; direction["UR"] = { -1,1 }; direction["DR"] = { 1,1 }; direction["DL"] = { 1,-1 }; cin >> t; while (t--) { cin >> n >> m >> i1 >> j_1 >> i2 >> j2 >> d; room = n * m * 4; dfs(i1, j_1, d,times); if (pd) cout << times << '\n'; else cout << -1 << '\n'; times = 0; pd = 0; } return 0; }
|
codeforces 950 div3
A
题目

难度比较低,字符串处理
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| #include <bits/stdc++.h> using namespace std;
string zimu[7]={"A","B","C","D","E","F","G"},inp,cha; int t,n,m,haxi[51],sum=0;
int main(void){ ios::sync_with_stdio(false); cin.tie(0);cout.tie(0); cin >> t; while(t--){ cin >> n >> m >> inp; while(m--){ for(int i=0;i<7;i++){ cha=zimu[i]; int it = inp.find(cha); if(it == -1) sum++; else inp[it]='0'; } } cout<<sum<<'\n'; sum=0;inp.clear(); } return 0; }
|
B
题目

这题考排序,不难,就是特判有点多
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| #include <bits/stdc++.h> using namespace std;
int t,n,f,k,fav,cache; vector <int> a; int main(void){ ios::sync_with_stdio(false); cin.tie(0);cout.tie(0); cin >> t; while(t--){ cin >> n >> f >> k; for(int i=0;i<n;i++){ cin >> cache; a.push_back(cache); } fav = a[f-1]; sort(a.begin(),a.end(),greater<int>()); if(a[k-1]<fav) cout << "YES" <<'\n'; else if(a[k-1]>fav) cout << "NO" <<'\n'; else if(n==1) cout << "YES" <<'\n'; else if(k<n && a[k]==fav) cout << "MAYBE" <<'\n'; else cout << "YES" <<'\n'; a.clear(); } return 0; }
|
C
题目

(这道题居然有156个test!)
题意大概是给你一个初始数组a,和现在的数组b,问你在m次变换(把a[c]赋值为d)后能否变成数组b。
map的搜索非常高效(这道题很坑,不用map几乎必定TLE)
1.如果d的最后一个不在b里,NO
2.如果b[d]==0,NO
否则YES
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| #include <bits/stdc++.h> using namespace std; int t, n, cache, m; vector <int> a,diff; map <int,int> b,d;
void noTLE(){ cin >> n; for (int i = 0; i < n; i++) { cin >> cache; a.push_back(cache); } for (int i = 0; i < n; i++) { cin >> cache; b[cache]++; if(a[i] != cache) diff.push_back(cache); } cin >> m; for (int i = 0; i < m; i++) { cin >> cache; d[cache]++; } if(b[cache]==0){ cout << "NO" <<'\n'; return; } for(auto i : diff){ if(d[i]==0){ cout << "NO" <<'\n'; return; } d[i]--; } cout << "YES" <<'\n'; return; }
int main(void) { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); cin >> t; while (t--) { noTLE(); diff.clear(); a.clear(); b.clear();d.clear(); } return 0; }
|
D
题目

这道题挺有难度,为了做这题我花了4小时恶补盲点
用欧几里得算法求出相邻数之间的最大公约数并记录到数组b里,然后用sec1和sec2两个子区间来判断切割a[i]后是否满足条件。还要首尾特判(真挺复杂的)
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| #include <bits/stdc++.h> using namespace std;
int t,n,cache,a[200001],b[200001]; int gcd(int a,int b){ return b==0 ? a:gcd(b,a%b); } void solve(){ int sec1[200001],sec2[200001];b[n]=99999999; for(int i=1;i<n;i++) b[i]=gcd(a[i],a[i+1]); sec1[0]=sec2[n-1]=sec2[n]=1; for(int i=1;i<n;i++) sec1[i] = sec1[i-1] && b[i-1] <= b[i]; for(int i=n-2;i>0;i--) sec2[i] = sec2[i+1] && b[i] <= b[i+1]; int ans = sec1[n-2] | sec2[2]; for(int i=2;i<n;i++){ int k = gcd(a[i-1],a[i+1]); ans |= sec1[i-2] && sec2[i+1] && k>=b[i-2] && k<=b[i+1]; } cout << (ans ? "YES\n" : "NO\n"); } int main(void){ ios::sync_with_stdio(false); cin.tie(0);cout.tie(0); cin >> t; while(t--){ cin >> n; for(int i=1;i<=n;i++){ cin>>cache; a[i]=cache; } solve(); } return 0; }
|
codeforces 871 div4
A
题目

字符串逐个字符比较,签到
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| #include <bits/stdc++.h> using namespace std;
int t,diff=0; string cf="codeforces",inp; int main(void){ ios::sync_with_stdio(false); cin.tie(0);cout.tie(0); cin >> t; while(t--){ cin >> inp; for(int i=0;i<10;i++){ if(cf[i]!=inp[i]) diff++; } cout << diff << '\n'; diff=0; } return 0; }
|
B
题目

求最长含0区间。本来第一思路是双指针的,结果写的时候发现还有更简单的方法,就按更简单的写了。但是双指针我没怎么练过,所以又写了一份双指针的代码。题不难,耗费的时间很少
两种方法的时间复杂度都是O(n),OJ上显示的用时也都是61ms
代码
easy
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| #include <bits/stdc++.h> using namespace std; int t,n,sum=0,sec=0,cache; int main(void){ ios::sync_with_stdio(false); cin.tie(0);cout.tie(0); cin >> t; while(t--){ cin >> n; for(int i=0;i<n;i++){ cin >> cache; if(cache==0) { sec++; sum=max(sum,sec); } else{ sum=max(sum,sec); sec=0; } } cout << sum << '\n'; sum=sec=0; } return 0; }
|
two pointers
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| #include <bits/stdc++.h> using namespace std;
int t,n,cache,a[101],sum=0; int main(void){ ios::sync_with_stdio(false); cin.tie(0);cout.tie(0); cin >> t; while(t--){ cin >> n; for(int i=0;i<n;i++){ cin >> cache; a[i]=cache+1; } if(n==1){ if(a[0]==1){ cout << 1 << '\n'; continue; } else{ cout << 0 << '\n'; continue; } } for(int l=0,r=0;l<n && r<n;){ if(a[l]==1 && a[r]==1){ sum = max(sum,r-l+1); r++; } else{ l=r+1;r=l; } } cout << sum <<'\n'; sum=0; } return 0; }
|
C
题目

输入的时候就处理,m01、m10、m11存放最小值,然后判断比较。这里需要注意m01、m10、m11初始化取的最大值不能为2e5+1,应为4e5+1(因为m01+m10的最值和可能为4e5,我搁这掉坑里了)
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| #include <bits/stdc++.h> using namespace std;
int t,n,m01=400001,m10=400001,m11=400001,ca,cm,book;
int main(void){ ios::sync_with_stdio(false); cin.tie(0);cout.tie(0); cin >> t; while(t--){ cin >> n; while(n--){ cin >> cm >> book; if(book == 10) m10 = min(m10,cm); else if(book == 01) m01 = min(m01,cm); else if(book == 11) m11 = min(m11,cm); } if(m11==400001 && (m01==400001 || m10==400001)) cout << -1 << '\n'; else cout << min(m11,m10+m01) << '\n'; m01=400001,m10=400001,m11=400001; } return 0; }
|
D
题目

给你一个数n,问你能不能把n拆分后出现数m,拆分的规则是拆成两个数后,一个数是另一个数的两倍。这题DFS搜,有个n==m的特判
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| #include <bits/stdc++.h> using namespace std; int t,n,m,cache; int dfs(int x){ if(x%3 != 0) return 0; else{ int x1 = x/3, x2 = x-x1; if(x1==m || x2==m) return 1; else{ int k =(dfs(x1)); if(!k) k = dfs(x2); return k; } } } int main(void){ ios::sync_with_stdio(false); cin.tie(0);cout.tie(0); cin >> t; while(t--){ cin >> n >> m; cout << ((dfs(n) || n==m ) ? "YES\n" : "NO\n"); } return 0; }
|
E
题目

二维格子里面,0表示陆地,非零表示湖泊,数字代表湖泊的深度。问相连的湖泊中最深的湖有多深。
BFS搜,用room[][]来判断路是否走过,走过的就不走
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| #include <bits/stdc++.h> using namespace std;
int room[1002][1002]={0},earth[1002][1002],t,n,m,cache; int explore[][2]={1,0,-1,0,0,1,0,-1}; struct wei{ int x,y; }; queue<wei> q; #define check (next.x>=0 && next.x<n && next.y>=0 && next.y<m && earth[next.x][next.y]!=0 && room[next.x][next.y]==0)
int bfs(int dx,int dy){ wei next,start; start.x=dx;start.y=dy;int sum=0; q.push(start);room[dx][dy]=1; while(!q.empty()){ start = q.front(); q.pop(); sum += earth[start.x][start.y]; for(int i=0;i<4;i++){ next.x=start.x+explore[i][0];next.y=start.y+explore[i][1]; if(check){ room[next.x][next.y]=1; q.push(next); } } } return sum; } int main(void){ ios::sync_with_stdio(false); cin.tie(0);cout.tie(0); cin >> t; while(t--){ cin >> n >> m; for(int i=0;i<n;i++){ for(int j=0;j<m;j++){ cin >> cache; earth[i][j]=cache; room[i][j]=0; } } int sum=0; for(int i=0;i<n;i++) for(int j=0;j<m;j++) if(earth[i][j] && room[i][j]==0) sum=max(sum,bfs(i,j)); cout << sum << '\n'; } return 0; }
|