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
");
38         }
39         else{
40             printf("NO
");
41         }
42     }
43  
44 }
A

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 }
View Code

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 }
View Code

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
", res);
101 }
View Code
原文地址:https://www.cnblogs.com/xwdzuishuai/p/11876444.html