AIM Tech Round 3 (Div. 2)

A

按题意模拟即可。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 int main () {
 5     int n, b, d; scanf("%d%d%d", &n, &b, &d);
 6     int now = 0, cnt = 0;
 7     for(int i = 1; i <= n; ++ i) {
 8         int x; scanf("%d", &x);
 9         if(x > b) continue;
10         now += x;
11         if(now > d) {
12             ++ cnt;
13             now = 0;
14         }
15     }
16     printf("%d\n", cnt);
17     return 0;
18 }
View Code

B

题意:在一个坐标轴上有n个点坐标为x1到xn,给一个a坐标,从这个点出发至少遍历n个点中的n - 1个,问最短距离是多少。

思路:贪心的思想,先往左后往右或者先往右后往左,注意特判一些特殊情况。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 int x[100005];
 5 int main () {
 6     int n, a; scanf("%d%d", &n, &a);
 7     for(int i = 1; i <= n; ++ i) scanf("%d", x + i);
 8     sort(x + 1, x + 1 + n);
 9     if(n == 1) return 0 * puts("0");
10     if(n == 2) return 0 * printf("%d\n", min(abs(a - x[1]), abs(a - x[2])));
11     if(a <= x[1]) return 0 * printf("%d\n", abs(a - x[n - 1]));
12     if(a >= x[n]) return 0 * printf("%d\n", abs(a - x[2]));
13     int ans1 = min(2 * abs(a - x[1]) + abs(a - x[n - 1]), abs(a - x[1]) + 2 * abs(a - x[n - 1]));
14     int ans2 = min(2 * abs(a - x[2]) + abs(a - x[n]), abs(a - x[2]) + 2 * abs(a - x[n]));
15     int ans = min(ans1, ans2);
16     if(a >= x[n - 1]) ans = min(ans, abs(a - x[1]));
17     if(a <= x[2]) ans = min(ans, abs(a - x[n]));
18     printf("%d\n", ans);
19     return 0;
20 }
View Code

C

题意:给一个字符串,要求选其中的一个连续子串,子串上的字符按照题目的规则转变,求执行转变之后字典序最小的字符串。

思路:贪心,选最左边的能转变成更小的字符串的字符作为子串的开始位置,往后直到遇到字符a停止。要注意的是题目要求严格执行一次操作,所以字符串一开始就都是a的情况,要把最后一个a变成z。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 char s[100005];
 5 int main () {
 6     scanf("%s", s);
 7     int len = strlen(s);
 8     bool use = false;
 9     for(int i = 0; i < len; ++ i) {
10         if(use && s[i] == 'a') break;
11         else if(s[i] != 'a') {
12             use = true;
13             s[i] --;
14         }
15     }
16     if(!use) s[len - 1] = 'z';
17     puts(s);
18     return 0;
19 }
View Code

D

题意:构造一个01串,其两个字符的子串00, 01, 10, 11的数量分别为a00, a01, a10, a11,如果存在这个01串,输出, 否则输出Impossible。

思路:从a00和a11的值我们可以算出字符串中0和1的个数,然后即可构造。但当a00,a11中有为0的情况下,需要特殊考虑。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 long long get(long long x) {
 5     long long l = 1, r = 1000000;
 6     while(l < r) {
 7         long long m = (l + r) >> 1;
 8         if(m * (m - 1) < 2 * x) l = m + 1;
 9         else r = m;
10     }
11     return l;
12 }
13 
14 int main () {
15     long long a, b, c, d; scanf("%lld%lld%lld%lld", &a, &b, &c, &d);
16     if(!a && !d) {
17         if(!b && !c) puts("1");
18         else if(!b) {
19             if(c == 1) puts("10");
20             else puts("Impossible");
21         } else if(!c) {
22             if(b == 1) puts("01");
23             else puts("Impossible");
24         } else puts("Impossible");
25     } else if(!a) {
26         long long one = get(d);
27         if(one * (one - 1) / 2 != d) return 0 * puts("Impossible");
28         if(!b && !c) {
29             for(int i = 1; i <= one; ++ i) printf("1"); puts("");
30         } else {
31             if(b + c == one) {
32                 for(int i = 1; i <= c; ++ i) printf("1");
33                 printf("0");
34                 for(int i = c + 1; i <= one; ++ i) printf("1");
35                 puts("");
36             } else puts("Impossible");
37         }
38     } else if(!d) {
39         long long zero = get(a);
40         if(zero * (zero - 1) / 2 != a) return 0 * puts("Impossible");
41         if(!b && !c) {
42             for(int i = 1; i <= zero; ++ i) printf("0"); puts("");
43         } else {
44             if(b + c == zero) {
45                 for(int i = 1; i <= b; ++ i) printf("0");
46                 printf("1");
47                 for(int i = b + 1; i <= zero; ++ i) printf("0");
48                 puts("");
49             } else puts("Impossible");
50         }
51     } else {
52         long long one = get(d), zero = get(a);
53         if(one * (one - 1) / 2 != d || zero * (zero - 1) / 2 != a) return 0 * puts("Impossible");
54         long long num = (one + zero) * (one + zero - 1) / 2 - a - d;
55         if(b + c != num) return 0 * puts("Impossible");
56         else {
57             int now1 = 0, now2 = 0;
58             while(now1 < zero || now2 < one) {
59                 if(b >= one - now2) {
60                     printf("0");
61                     b -= one - now2;
62                     now1 ++;
63                 } else {
64                     printf("1");
65                     now2 ++;
66                 }
67             } puts("");
68         }
69     }
70     return 0;
71 }
View Code

E

题意:给一颗n个节点的树,对于树的每一个节点,进行一次操作后,问它是否能成为质心(centroid),质心是指去掉这个点后,剩下的每个联通的子树的最大节点不超过n/2。

操作是先删除一条已有的边,然后再连一条新的边。

思路:考虑树形dp,dp1[u]表示以u为根节点时,它的子树最大可分裂出的节点数, 然后一遍dfs求以1为根的情况再一遍dfs求答案即可。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 int idxE;
 5 struct EDGE {
 6     int v, next;
 7 }edge[400005 << 1];
 8 int head[400005];
 9 
10 void add_edge(int u, int v) {
11     ++ idxE;
12     edge[idxE].v = v;
13     edge[idxE].next = head[u];
14     head[u] = idxE;
15 }
16 
17 int n, ans[400005];
18 int sz[400005], dp1[400005], dp2[400004];
19 
20 void dfs(int u, int fa) {
21     sz[u] = 1;
22     for(int i = head[u]; i; i = edge[i].next) if(edge[i].v != fa) {
23         int v = edge[i].v;
24         dfs(v, u);
25         sz[u] += sz[v];
26         dp1[u] = max(dp1[u], dp1[v]);
27     }
28     if(sz[u] <= n / 2) dp1[u] = sz[u];
29 }
30 
31 void getans(int u, int fa) {
32     ans[u] = 1;
33     if(sz[u] <= n / 2) {
34         if(n - sz[u] - dp2[u] > n / 2) ans[u] = 0;
35     } else {
36         for(int i = head[u]; i; i = edge[i].next) if(edge[i].v != fa) {
37             int v = edge[i].v;
38             if(sz[v] - dp1[v] > n / 2) ans[u] = 0;
39         }
40     }
41     int ma = -1, mav;
42     for(int i = head[u]; i; i = edge[i].next) if(edge[i].v != fa) {
43         int v = edge[i].v;
44         if(dp1[v] > ma) ma = dp1[v], mav = v;
45     }
46     for(int i = head[u]; i; i = edge[i].next) if(edge[i].v != fa) {
47         int v = edge[i].v;
48         if(v == mav) {
49             dp2[v] = dp2[u];
50             for(int j = head[u]; j; j = edge[j].next) if(edge[j].v != mav && edge[j].v != fa) {
51                 int vv = edge[j].v;
52                 dp2[v] = max(dp2[v], dp1[vv]);
53             }
54         } else dp2[v] = max(dp2[u], ma);
55         if(n - sz[v] <= n / 2) dp2[v] = n - sz[v];
56         getans(v, u);
57     }
58 }
59 
60 int main () {
61     scanf("%d", &n);
62     for(int i = 1; i <= n - 1; ++ i) {
63         int u, v; scanf("%d%d", &u, &v);
64         add_edge(u, v), add_edge(v, u);
65     }
66     dfs(1, -1);
67     getans(1, -1);
68     for(int i = 1; i <= n; ++ i) printf("%d ", ans[i]);
69     return 0;
70 }
View Code

 

posted @ 2016-08-25 14:41  youqiong  阅读(137)  评论(0编辑  收藏  举报