codeforces-1157 (div3)
赛后经验:疲劳做题不可取。
这场状态不好,写的代码质量不高,仅供参考
A.map打vis标记,按照题意模拟即可。
WA原因:int变量用%lld输出
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <map> #include <set> #include <ctime> #include <cmath> #include <queue> #include <stack> #include <vector> #include <string> #include <cstdio> #include <cstdlib> #include <cstring> #include <sstream> #include <iostream> #include <algorithm> #include <functional> using namespace std; #define For(i, x, y) for(int i=x;i<=y;i++) #define _For(i, x, y) for(int i=x;i>=y;i--) #define Mem(f, x) memset(f,x,sizeof(f)) #define Sca(x) scanf("%d", &x) #define Sca2(x,y) scanf("%d%d",&x,&y) #define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z) #define Scl(x) scanf("%lld",&x); #define Pri(x) printf("%d\n", x) #define Prl(x) printf("%lld\n",x); #define CLR(u) for(int i=0;i<=N;i++)u[i].clear(); #define LL long long #define ULL unsigned long long #define mp make_pair #define PII pair<int,int> #define PIL pair<int,long long> #define PLL pair<long long,long long> #define pb push_back #define fi first #define se second typedef vector<int> VI; int read(){int x = 0,f = 1;char c = getchar();while (c<'0' || c>'9'){if (c == '-') f = -1;c = getchar();} while (c >= '0'&&c <= '9'){x = x * 10 + c - '0';c = getchar();}return x*f;} const double eps = 1e-9; const int maxn = 110; const int INF = 0x3f3f3f3f; const int mod = 1e9 + 7; int N,M,K; map<LL,bool>P,Q; int main(){ LL x; Scl(x); int ans = 0; while(1){ if(!P[x]){ P[x] = 1; ans++; }else break; x++; while(x && !(x % 10)) x /= 10; } Pri(ans); return 0; }
B.很显然从开头开始能变大就变大,连续一段区间就是从第一个可以变大的数字开头往后面所有能变大就变大的数字,遇到变小就停止
WA原因:没看到连续区间这个条件
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <map> #include <set> #include <ctime> #include <cmath> #include <queue> #include <stack> #include <vector> #include <string> #include <cstdio> #include <cstdlib> #include <cstring> #include <sstream> #include <iostream> #include <algorithm> #include <functional> using namespace std; #define For(i, x, y) for(int i=x;i<=y;i++) #define _For(i, x, y) for(int i=x;i>=y;i--) #define Mem(f, x) memset(f,x,sizeof(f)) #define Sca(x) scanf("%d", &x) #define Sca2(x,y) scanf("%d%d",&x,&y) #define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z) #define Scl(x) scanf("%lld",&x); #define Pri(x) printf("%d\n", x) #define Prl(x) printf("%lld\n",x); #define CLR(u) for(int i=0;i<=N;i++)u[i].clear(); #define LL long long #define ULL unsigned long long #define mp make_pair #define PII pair<int,int> #define PIL pair<int,long long> #define PLL pair<long long,long long> #define pb push_back #define fi first #define se second typedef vector<int> VI; int read(){int x = 0,f = 1;char c = getchar();while (c<'0' || c>'9'){if (c == '-') f = -1;c = getchar();} while (c >= '0'&&c <= '9'){x = x * 10 + c - '0';c = getchar();}return x*f;} const double eps = 1e-9; const int maxn = 2e5 + 10; const int INF = 0x3f3f3f3f; const int mod = 1e9 + 7; int N,M,K; char str[maxn]; int to[20]; int main(){ Sca(N); scanf("%s",str + 1); for(int i = 1; i <= 9 ; i ++) Sca(to[i]); int start = 2; for(int i = 1; i <= N ; i ++){ int id = str[i] - '0'; if(id < to[id] && start){ id = to[id]; start = 1; }else if(id > to[id] && start == 1){ start = 0; } printf("%d",id); } return 0; }
C1,C2.
贪心做法,不断往两端取较小的那一个,遇到一样的就会发现如果取左边之后就只能从左边取,反之只能从右边取。
比较一下哪个大就可以了
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <map> #include <set> #include <ctime> #include <cmath> #include <queue> #include <stack> #include <vector> #include <string> #include <cstdio> #include <cstdlib> #include <cstring> #include <sstream> #include <iostream> #include <algorithm> #include <functional> using namespace std; #define For(i, x, y) for(int i=x;i<=y;i++) #define _For(i, x, y) for(int i=x;i>=y;i--) #define Mem(f, x) memset(f,x,sizeof(f)) #define Sca(x) scanf("%d", &x) #define Sca2(x,y) scanf("%d%d",&x,&y) #define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z) #define Scl(x) scanf("%lld",&x); #define Pri(x) printf("%d\n", x) #define Prl(x) printf("%lld\n",x); #define CLR(u) for(int i=0;i<=N;i++)u[i].clear(); #define LL long long #define ULL unsigned long long #define mp make_pair #define PII pair<int,int> #define PIL pair<int,long long> #define PLL pair<long long,long long> #define pb push_back #define fi first #define se second typedef vector<int> VI; int read(){int x = 0,f = 1;char c = getchar();while (c<'0' || c>'9'){if (c == '-') f = -1;c = getchar();} while (c >= '0'&&c <= '9'){x = x * 10 + c - '0';c = getchar();}return x*f;} const double eps = 1e-9; const int maxn = 4e5 + 10; const int INF = 0x3f3f3f3f; const int mod = 1e9 + 7; int N,M,K; int a[maxn]; string s; int main(){ Sca(N); for(int i = 1; i <= N ; i ++) Sca(a[i]); int l = 1,r = N; int ans = 0; int MIN = 0; while(1){ if(l > r || (a[l] <= MIN && a[r] <= MIN)) break; if((a[l] > MIN && a[l] < a[r]) || a[r] <= MIN){ ans++; MIN = a[l]; l++; s.pb('L'); }else if(a[r] > MIN && a[l] != a[r]){ ans++; MIN = a[r]; r--; s.pb('R'); }else if(a[l] == a[r]){ int L = l,R = r; int tmp1 = 0,tmp2 = 0; int p = MIN; while(L <= r && a[L] > p){ tmp1++; p = a[L]; L++; } p = MIN; while(l <= R && a[R] > p){ tmp2++; p = a[R]; R--; } ans += max(tmp1,tmp2); if(tmp1 > tmp2){ while(tmp1--) s.pb('L'); }else{ while(tmp2--) s.pb('R'); } break; } } Pri(ans); cout << s << endl; return 0; }
D.首先排除掉题目过少天数过多的情况,也就是K < N * ( N + 1 ) / 2必定为NO
其次构造一个N天,一开始数目为1,2,3,4...N
然后给他们全部加上一个数字K / N,就会发现必定也符合题意,剩余的就从后面开始往前面填充就可以了。
WA原因:忘记输出YES了
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <map> #include <set> #include <ctime> #include <cmath> #include <queue> #include <stack> #include <vector> #include <string> #include <cstdio> #include <cstdlib> #include <cstring> #include <sstream> #include <iostream> #include <algorithm> #include <functional> using namespace std; #define For(i, x, y) for(int i=x;i<=y;i++) #define _For(i, x, y) for(int i=x;i>=y;i--) #define Mem(f, x) memset(f,x,sizeof(f)) #define Sca(x) scanf("%d", &x) #define Sca2(x,y) scanf("%d%d",&x,&y) #define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z) #define Scl(x) scanf("%lld",&x); #define Pri(x) printf("%d\n", x) #define Prl(x) printf("%lld\n",x); #define CLR(u) for(int i=0;i<=N;i++)u[i].clear(); #define LL long long #define ULL unsigned long long #define mp make_pair #define PII pair<int,int> #define PIL pair<int,long long> #define PLL pair<long long,long long> #define pb push_back #define fi first #define se second typedef vector<int> VI; int read(){int x = 0,f = 1;char c = getchar();while (c<'0' || c>'9'){if (c == '-') f = -1;c = getchar();} while (c >= '0'&&c <= '9'){x = x * 10 + c - '0';c = getchar();}return x*f;} const double eps = 1e-9; const int maxn = 100010; const int INF = 0x3f3f3f3f; const int mod = 1e9 + 7; LL N,K; int a[maxn]; int main(){ scanf("%lld%lld",&K,&N); if(N * (N + 1) / 2 > K){ puts("NO"); return 0; } for(int i = 1; i <= N ; i ++) a[i] = i; int cnt = N; K -= N * (N + 1) / 2; int add = K / N; for(int i = 1; i <= N ; i ++) a[i] += add; K -= add * N; for(int i = N; i >= 2 && K; i --){ int t = min(K,1LL * a[i - 1] * 2 - a[i]); K -= t; a[i] += t; } if(K){ puts("NO"); return 0; } puts("YES"); for(int i = 1; i <= N ; i ++) printf("%d ",a[i]); return 0; }
E.很显然还是贪心,从前面往后贪心,定义一个数x的兄弟为(N - x) % N,显然他俩匹配的时候和为0是最好的,其次是比它兄弟大的越小越好
那很显然每次都寻找他兄弟或者最接近他兄弟的那个数,这个过程常规可以二分,并查集可以去掉log,时间复杂度O(n)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <map> #include <set> #include <ctime> #include <cmath> #include <queue> #include <stack> #include <vector> #include <string> #include <cstdio> #include <cstdlib> #include <cstring> #include <sstream> #include <iostream> #include <algorithm> #include <functional> using namespace std; #define For(i, x, y) for(int i=x;i<=y;i++) #define _For(i, x, y) for(int i=x;i>=y;i--) #define Mem(f, x) memset(f,x,sizeof(f)) #define Sca(x) scanf("%d", &x) #define Sca2(x,y) scanf("%d%d",&x,&y) #define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z) #define Scl(x) scanf("%lld",&x); #define Pri(x) printf("%d\n", x) #define Prl(x) printf("%lld\n",x); #define CLR(u) for(int i=0;i<=N;i++)u[i].clear(); #define LL long long #define ULL unsigned long long #define mp make_pair #define PII pair<int,int> #define PIL pair<int,long long> #define PLL pair<long long,long long> #define pb push_back #define fi first #define se second typedef vector<int> VI; int read(){int x = 0,f = 1;char c = getchar();while (c<'0' || c>'9'){if (c == '-') f = -1;c = getchar();} while (c >= '0'&&c <= '9'){x = x * 10 + c - '0';c = getchar();}return x*f;} const double eps = 1e-9; const int maxn = 2e5 + 10; const int INF = 0x3f3f3f3f; const int mod = 1e9 + 7; int N,M,K; int a[maxn],b[maxn]; int fa[maxn]; void init(){ for(int i = 0 ; i <= N ; i ++) fa[i] = i; } int find(int t){ if(fa[t] == t) return t; return fa[t] = find(fa[t]); } void Union(int a,int b){ a = find(a); b = find(b); if(a == b) return; fa[a] = b; } int num[maxn]; int main(){ Sca(N); init();; for(int i = 1; i <= N; i ++){ Sca(a[i]); a[i] %= N; } for(int i = 1; i <= N; i ++){ Sca(b[i]); b[i] %= N; num[b[i]]++; } for(int i = 0 ; i < N ; i ++){ if(!num[i]) Union(i,(i + 1) % N); } for(int i = 1; i <= N ; i ++){ int k = find((N - a[i]) % N); printf("%d ",(a[i] + k) % N); num[k]--; if(!num[k]) Union(k,(k + 1) % N); } return 0; }
F.很显然一个数出现超过两次就可以实现这个环一次过去一次回来,这被称为白给
寻找最多的连续的白给的数,找出最大值就可以了,这还可以用并查集维护。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <map> #include <set> #include <ctime> #include <cmath> #include <queue> #include <stack> #include <vector> #include <string> #include <cstdio> #include <cstdlib> #include <cstring> #include <sstream> #include <iostream> #include <algorithm> #include <functional> using namespace std; #define For(i, x, y) for(int i=x;i<=y;i++) #define _For(i, x, y) for(int i=x;i>=y;i--) #define Mem(f, x) memset(f,x,sizeof(f)) #define Sca(x) scanf("%d", &x) #define Sca2(x,y) scanf("%d%d",&x,&y) #define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z) #define Scl(x) scanf("%lld",&x); #define Pri(x) printf("%d\n", x) #define Prl(x) printf("%lld\n",x); #define CLR(u) for(int i=0;i<=N;i++)u[i].clear(); #define LL long long #define ULL unsigned long long #define mp make_pair #define PII pair<int,int> #define PIL pair<int,long long> #define PLL pair<long long,long long> #define pb push_back #define fi first #define se second typedef vector<int> VI; int read(){int x = 0,f = 1;char c = getchar();while (c<'0' || c>'9'){if (c == '-') f = -1;c = getchar();} while (c >= '0'&&c <= '9'){x = x * 10 + c - '0';c = getchar();}return x*f;} const double eps = 1e-9; const int maxn = 2e5 + 110; const int INF = 0x3f3f3f3f; const int mod = 1e9 + 7; int N,M,K; int a[maxn]; int num[maxn]; int pre[maxn]; int fa[maxn]; void init(){ for(int i = 0 ; i < maxn; i ++) fa[i] = i; } int find(int x){ if(x == fa[x]) return x; return fa[x] = find(fa[x]); } void Union(int a,int b){ a = find(a); b = find(b); fa[a] = b; } int main(){ Sca(N); init(); for(int i = 1; i <= N ; i ++){ Sca(a[i]); num[a[i]]++; } for(int i = 1; i <= 2e5 + 20; i ++) pre[i] = pre[i - 1] + num[i]; for(int i = 2e5 + 20; i >= 1; i --){ if(num[i] >= 2 && num[i + 1] >= 2) Union(i,i + 1); } int p; int ans = 0; for(int i = 1; i <= 2e5 + 20; i ++){ int to = find(i + 1); if(num[to] >= 2) to++; if(pre[to] - pre[i - 1] > ans){ ans = pre[to] - pre[i - 1]; p = i; } } Pri(ans); int to = find(p + 1); if(num[to] >= 2) to++; for(int i = p; i <= to; i ++){ if(num[i]){ printf("%d ",i); num[i]--; } } for(int i = to; i >= p; i --){ for(int j = 0; j < num[i]; j ++) printf("%d ",i); } return 0; }
G.很显然所有矩阵最多只有一行会同时出现0和1,枚举这行中间的交界点就可以得出所有的竖着是否翻转的情况。
知道了之后又通过这一行上面全0,下面全1,这一行左边全0,右边全1的限制条件下知道所有横着的是否翻转。
直接check就可以
WA原因:少一句特判
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <map> #include <set> #include <ctime> #include <cmath> #include <queue> #include <stack> #include <vector> #include <string> #include <cstdio> #include <cstdlib> #include <cstring> #include <sstream> #include <iostream> #include <algorithm> #include <functional> using namespace std; #define For(i, x, y) for(int i=x;i<=y;i++) #define _For(i, x, y) for(int i=x;i>=y;i--) #define Mem(f, x) memset(f,x,sizeof(f)) #define Sca(x) scanf("%d", &x) #define Sca2(x,y) scanf("%d%d",&x,&y) #define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z) #define Scl(x) scanf("%lld",&x); #define Pri(x) printf("%d\n", x) #define Prl(x) printf("%lld\n",x); #define CLR(u) for(int i=0;i<=N;i++)u[i].clear(); #define LL long long #define ULL unsigned long long #define mp make_pair #define PII pair<int,int> #define PIL pair<int,long long> #define PLL pair<long long,long long> #define pb push_back #define fi first #define se second typedef vector<int> VI; int read(){int x = 0,f = 1;char c = getchar();while (c<'0' || c>'9'){if (c == '-') f = -1;c = getchar();} while (c >= '0'&&c <= '9'){x = x * 10 + c - '0';c = getchar();}return x*f;} const double eps = 1e-9; const int maxn = 210; const int INF = 0x3f3f3f3f; const int mod = 1e9 + 7; int N,M,K; int a[maxn][maxn]; int cul[maxn],row[maxn]; bool check(){ int p = 0; for(int i = 1; i <= N ; i ++){ int x = cul[1] ^ a[i][1]; for(int j = 2; j <= M; j ++){ if((cul[j] ^ a[i][j]) != x){ if(p != i && p) return false; p = i; } } } if(p){ if((cul[1] ^ a[p][1]) == 1) row[p] = 1; else row[p] = 0; int flag = 0; for(int i = 1; i <= M ; i ++){ int x = cul[i] ^ a[p][i]; if(x == 1){ flag = 1; }else if(x == 0){ if(flag) return false; } } } for(int i = 1; i < p ; i ++){ if((cul[1] ^ a[i][1]) == 1) row[i] = 1; else row[i] = 0; } for(int i = p + 1; i <= N ; i ++){ if((cul[1] ^ a[i][1]) == 1) row[i] = 0; else row[i] = 1; } return true; } int main(){ Sca2(N,M); for(int i = 1; i <= N ; i ++){ for(int j = 1; j <= M ; j ++){ Sca(a[i][j]); } } for(int i = 1; i <= M + 1; i ++){ for(int j = 1; j < i ; j ++){ if(a[1][j] == 1) cul[j] = 1; else cul[j] = 0; } for(int j = i; j <= M; j ++){ if(a[1][j] == 1) cul[j] = 0; else cul[j] = 1; } int flag = 0; if(check()) flag = 1; if(flag){ puts("YES"); for(int i = 1; i <= N ; i ++) printf("%d",row[i]); puts(""); for(int i = 1; i <= M ; i ++) printf("%d",cul[i]); return 0; } } puts("NO"); return 0; }