codeforces#600(div2)
A - Single Push
题面意思,在给a数组取l - r加上k, 当a[i] - b[i] > 0 时,不成立,当出现0 - x - 0 - x的情况成立,当出现0 - x - y -0的情况不成立。那么其实只要在边界加上0,问题就变成了0 -x- 0活0 -0-0情况。
1 #include <cstdio> 2 3 int main(){ 4 int t, n, a[100002], b[100002], c[100002]; 5 6 scanf("%d", &t); 7 8 for(int i = 0; i < t; i++){ 9 scanf("%d", &n); 10 11 for(int j = 0; j < n; j++){ 12 scanf("%d", &a[j]); 13 } 14 for(int j = 0; j < n; j++){ 15 scanf("%d", &b[j]); 16 } 17 18 for(int j = 0; j < n; j++){ 19 c[j+1] = b[j] - a[j]; 20 } 21 c[0] = 0; 22 c[n + 1] = 0; 23 24 int count = 0; 25 for(int j = 0; j <= n; j++){ 26 if(c[j] < 0){ 27 count = 3; 28 break; 29 } 30 31 if(c[j] != c[j + 1]) 32 count++; 33 } 34 35 36 if(count <= 2){ 37 printf("YES\n"); 38 } 39 else{ 40 printf("NO\n"); 41 } 42 } 43 44 }
B - Silly Mistake
题面意思,把一个区间分别k区间,k个区间内满足,出现+x 必须出现-x,且同样的x不能出现在一个区间内出现俩次。
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 const int N = 1e5 + 10; 6 7 int n; 8 int T; 9 int a[N]; 10 set<int> q; 11 vector<int> ans; 12 map<int, int> ma; 13 14 int main() 15 { 16 17 18 ma.clear(); 19 ans.clear(); 20 q.clear(); 21 scanf("%d", &n); 22 23 for (int i = 1; i <= n; i ++) 24 scanf("%d", &a[i]); 25 // cout << a[1] << endl; 26 bool flag = true; 27 for (int i = 1; i <= n; i ++) 28 { 29 // cout << a[i] << endl; 30 if(a[i] < 0) 31 { 32 // cout << a[i] << endl; 33 if(q.find(-a[i]) == q.end()) 34 { 35 flag = false; 36 break; 37 } 38 else 39 { 40 q.erase(-a[i]); 41 // cout << q.size() << endl; 42 if(q.size() == 0) 43 { 44 ans.push_back(i); 45 ma.clear(); 46 } 47 } 48 } 49 else 50 { 51 if(ma[a[i]]) 52 { 53 flag = false; 54 break; 55 } 56 else if(!ma[a[i]]) 57 { 58 q.insert(a[i]); 59 ma[a[i]] = 1; 60 } 61 } 62 } 63 if(q.size() > 0) 64 { 65 flag = false; 66 } 67 if(!flag ) 68 { 69 puts("-1"); 70 return 0; 71 } 72 cout << ans.size() << endl; 73 for (int i = 0; i < ans.size(); i ++) 74 { 75 if(i == 0) 76 { 77 cout << ans[i] << " "; 78 } 79 else 80 { 81 cout << ans[i] - ans[i - 1] << " "; 82 } 83 } 84 85 }
C - Sweets Eating
题面意思,吃糖, 每天最多吃m个糖,那么吃糖会有一个值d * a[i], d为第几天吃,让你求吃1~n个糖的值得最小值。那么对于k个糖来说,a[i]越大的糖必须越先吃,才能使值最小,对于前i个糖, 那么它比前i - 1吃的糖的值,多出a[i] + a[i - m] + a[i - 2 *m] .... a[i - k * m],用前缀和来维护。
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 const int N = 2e5 + 10; 6 typedef long long ll; 7 8 ll n, m; 9 ll a[N]; 10 ll sum[N]; 11 ll ans[N]; 12 13 int main() 14 { 15 scanf("%lld%lld", &n, &m); 16 for (int i = 1; i <= n; i ++) 17 { 18 scanf("%lld", &a[i]); 19 } 20 sort(a + 1, a + n + 1); 21 for (int i = 1; i <= m; i ++) 22 sum[i] = a[i]; 23 for (int i = m; i <= n; i ++) 24 { 25 sum[i] = sum[i - m] + a[i]; 26 } 27 for (int i = 1; i <= n; i ++) 28 { 29 ans[i] = ans[i - 1]; 30 ans[i] += sum[i]; 31 } 32 for (int i = 1; i <= n; i ++) 33 printf("%lld ", ans[i]); 34 35 }
D - Harmonious Graph
体面意思,给你一个无向图,然后对于任意一个联通块的最大点数r和最小的点数l,都存在r - l + 1 == 联通块的个数,所以可以先跑个tarjan求出联通块的数量,并记录联通块的最大值和最小值,根据左端点排序,那么现在来合并联通块, 对于要合并的联通块,一定存在交集,Li 一顶小于Ri + 1,此时把联通块合在一个更新R。
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 const int N = 3e5 + 10; 6 const int M = 6e5 + 10; 7 const int INF = 0x3f3f3f3f; 8 9 10 11 int n, m; 12 int h[N], e[M], ne[M], idx; 13 int dfn[N], low[N], stac[N], num; 14 int top, st[N]; 15 int cnt; 16 int c[N]; 17 int p[N]; 18 set<int> s[N]; 19 void add(int a, int b) 20 { 21 e[idx] = b; 22 ne[idx] = h[a]; 23 h[a] = idx ++; 24 } 25 void tarjan(int u) 26 { 27 dfn[u] = low[u] = ++ num; 28 stac[++ top] = u; 29 st[u] = 1; 30 for (int i = h[u]; ~i; i = ne[i]) 31 { 32 int j = e[i]; 33 if(!dfn[j]) 34 { 35 tarjan(j); 36 low[u] = min(low[u], low[j]); 37 } 38 else if(st[j]) 39 low[u] = min(low[u], dfn[j]); 40 } 41 if(dfn[u] == low[u]) 42 { 43 ++ cnt; 44 int z; 45 do{ 46 z = stac[top --]; 47 st[z] = 0; 48 c[z] = cnt; 49 p[z] = u; 50 s[cnt].insert(z); 51 }while(z != u); 52 } 53 } 54 55 int find(int x) 56 { 57 if(x == p[x]) return x; 58 return p[x] = find(p[x]); 59 } 60 61 62 int main() 63 { 64 memset(h, -1, sizeof(h)); 65 scanf("%d%d", &n, &m); 66 for (int i = 1; i <= m; i ++) 67 { 68 int a, b; 69 scanf("%d%d", &a, &b); 70 add(a, b), add(b, a); 71 } 72 73 for (int i = 1; i <= n; i ++) 74 { 75 if(!dfn[i]) 76 tarjan(i); 77 } 78 for (int i = 1; i <= cnt; i ++) 79 { 80 p[i] = i; 81 } 82 83 int res = 0; 84 int now = -1; 85 sort(s + 1, s + cnt + 1); 86 for (int i = 1; i <= cnt; i ++) 87 { 88 int r = *(--s[i].end()), l = *s[i].begin(); 89 if(now == -1) 90 { 91 now = r; 92 } 93 else 94 { 95 if(l < now) res ++; 96 now = max(r, now); 97 } 98 99 } 100 printf("%d\n", res); 101 }