AIM Tech Round 3 (Div. 2)

5/5

这一场是比较水的一场(当然我是指div2),所以前面三题就略过吧。。。

题D D. Recover the String

题意:让你构造一个01串,给你00,01,10,11的子序列个数,问你有没有满足的串。

题解:这题实际上并不难, 只是分类讨论有点麻烦。

首先是00和11一定是满足n * (n - 1)  / 2,先判定一下

然后得到0的个数x,1的个数y

然后我们注意到,现一开始所有的0放在一起,然后插入一个位置k,那么我们发现01多了k,10多了x – k;假设这y个1 的位置是k1,k2,……,ky,然后01的个数和是sum{ki},然后10的和为xy -sum{ki},只要先放多个1在最右端,然后将余数放在中间某个位置即可。这个很容易想到,关键是易错点:0和1的个数为0和1的时候要特判,为了避免出错,代码写得恶心一点也无妨。。

  1 /*zhen hao*/
  2 #include <bits/stdc++.h>
  3 using namespace std;
  4
  5 #define lson l, m, rt*2
  6 #define rson m + 1, r, rt*2+1
  7 #define X first
  8 #define Y second
  9
 10 typedef pair<int,int> PII;
 11 typedef long long LL;
 12 typedef unsigned long long ULL;
 13
 14 const int N = 1e9;
 15 vector<LL> v;
 16
 17 void init() {
 18   for (int i = 1; ; i++) {
 19     if (1LL * i * (i - 1) / 2 > N) break;
 20     v.push_back(1LL * i * (i - 1) / 2);
 21   }
 22 }
 23
 24 int get_num(LL x) {
 25   int p = lower_bound(v.begin(), v.end(), x) - v.begin();
 26   if (v[p] != x) return -1;
 27   else return p + 1;
 28 }
 29
 30 char ans[1000010];
 31
 32 int main() {
 33 //  freopen("case.in", "r", stdin);
 34   init();
 35   LL a00, a01, a10, a11;
 36   cin >> a00 >> a01 >> a10 >> a11;
 37 //  cout << get_num(a00) << ‘ ‘ << get_num(a11) << endl;
 38   int x = get_num(a00), y = get_num(a11);
 39 //  cout << x << ‘ ‘ << y << endl;
 40   if (x == -1 || y == -1) {
 41     puts("Impossible");
 42     return 0;
 43   }
 44   if (a00 == 0) {
 45     if (a11 == 0) {
 46       if (a01 == 0 && a10 == 0) puts("0");
 47       else if (a01 == 1 && a10 == 0) puts("01");
 48       else if (a01 == 0 && a10 == 1) puts("10");
 49       else puts("Impossible");
 50     }
 51     else {
 52       if (a01 + a10 == y) {
 53         for (int i = 0; i < y - a01; i++) putchar(‘1‘);
 54         putchar(‘0‘);
 55         for (int i = 0; i < a01; i++) putchar(‘1‘);
 56         puts("");
 57       }
 58       else if (a01 + a10 == 0) {
 59         for (int i = 0; i < y; i++) putchar(‘1‘);
 60         puts("");
 61       }
 62       else puts("Impossible");
 63     }
 64     return 0;
 65   }
 66   if (a11 == 0) {
 67     if (a01 + a10 == x) {
 68       for (int i = 0; i < x - a10; i++) putchar(‘0‘);
 69       putchar(‘1‘);
 70       for (int i = 0; i < a10; i++) putchar(‘0‘);
 71       puts("");
 72     }
 73     else if (a01 + a10 == 0) {
 74       for (int i = 0; i < x; i++) putchar(‘0‘);
 75       puts("");
 76     }
 77     else puts("Impossible");
 78     return 0;
 79   }
 80   if (1LL * x * y != a01 + a10) {
 81     puts("Impossible");
 82     return 0;
 83   }
 84   int head = a01 / y, mid = a01 % y != 0, tail = x - head - mid;
 85   if (head > x || tail < 0) {
 86     puts("Impossible");
 87     return 0;
 88   }
 89   int cnt = 0;
 90   for (int i = 0; i < head; i++) ans[cnt++] = ‘0‘;
 91   if (mid) {
 92     int num = a01 % y;
 93     for (int i = 0; i < y - num; i++) ans[cnt++] = ‘1‘;
 94     ans[cnt++] = ‘0‘;
 95     for (int i = 0; i < num; i++) ans[cnt++] = ‘1‘;
 96   }
 97   else {
 98     for (int i = 0; i < y; i++) ans[cnt++] = ‘1‘;
 99   }
100   for (int i = 0; i < tail; i++) ans[cnt++] = ‘0‘;
101   puts(ans);
102   return 0;
103 }

代码君

题E

题意:定义“删边”,将一条边删掉分成两个子树,其中一棵子树可以任意接在另一棵子树的任意结点上,给你一棵树,对于每个点问你能不能通过至多删掉一条边使得这个点成为重心。

题解:实际上做法很简单易懂,对于一个点使得以它为根,然后找出最大的一个子树,然后问你这棵子树能不能分出一个子树的size为x,使得x <= n / 2,然后剩余的子树的size也是<=n / 2。所以我们只要对于每个点求出一个val[v]表示以他为根的子树v中最大的分出的size不超过n / 2是多少,然后对于每个子树size[v] – val[v] <= n / 2均满足即可。如果单纯地做复杂度是O(n ^ 2)。要利用dp的思想任意选一个点为根,然后dfs三次,第一次求出sz[v]表示这棵子树的size,并且转化成有根树。第二次dfs求出down[v]表示以v为根的子树中最大的不超过n / 2的子树的size是多少。第三次就是求出最up[v]表示除了v这个子树的另外一个子树的结点不超过n / 2的最大子树(这个比较麻烦,要记录最大和次大,然后传递给子树具体看代码)。

 1 /*zhen hao*/
 2 #include <bits/stdc++.h>
 3 using namespace std;
 4
 5 #define lson l, m, rt*2
 6 #define rson m + 1, r, rt*2+1
 7 #define X first
 8 #define Y second
 9
10 typedef pair<int,int> PII;
11 typedef long long LL;
12 typedef unsigned long long ULL;
13
14 const int N = 4e5 + 10;
15 int up[N], down[N], sz[N], fa[N];
16 int n;
17
18 vector<int> g[N];
19
20 void dfs_sz(int u, int p = - 1) {
21   sz[u] = 1;
22   fa[u] = p;
23   for (int i = 0; i < (int)g[u].size(); i++) {
24     int v = g[u][i];
25     if (v == p) continue;
26     dfs_sz(v, u);
27     sz[u] += sz[v];
28   }
29 }
30
31 void dfs_down(int u, int p = -1) {
32   if (sz[u] <= n / 2) down[u] = sz[u];
33   for (int i = 0; i < (int)g[u].size(); i++) {
34     int v = g[u][i];
35     if (v == p) continue;
36     dfs_down(v, u);
37     down[u] = max(down[u], down[v]);
38   }
39 }
40
41 void dfs_up(int u, int p = -1, int pre = 0) {
42 //  cout << u << ‘ ‘ << p << ‘ ‘ << pre << endl;
43   up[u] = n - sz[u] <= n / 2 ? n - sz[u] : pre;
44   int _max = 0, next_max = 0;
45   for (int i = 0; i < (int)g[u].size(); i++) {
46     int v = g[u][i];
47     if (v == p) continue;
48     if (down[v] >= _max) {
49       next_max = _max;
50       _max = down[v];
51     }
52     else if (down[v] >= next_max) {
53       next_max = down[v];
54     }
55   }
56   for (int i = 0; i < (int)g[u].size(); i++) {
57     int v = g[u][i];
58     if (v == p) continue;
59     if (down[v] == _max) dfs_up(v, u, max(up[u], next_max));
60     else dfs_up(v, u, max(up[u], _max));
61   }
62 }
63
64 int main() {
65 //  freopen("case.in", "r", stdin);
66   cin >> n;
67   for (int i = 0; i < n - 1; i++) {
68     int u, v;
69     scanf("%d%d", &u, &v);
70     u--; v--;
71     g[u].push_back(v);
72     g[v].push_back(u);
73   }
74   dfs_sz(0);
75   dfs_down(0);
76   dfs_up(0);
77 //  for (int i = 0; i < n; i++) cout << sz[i] << ‘ ‘ << down[i] << ‘ ‘ << up[i] << endl;
78   for (int u = 0; u < n; u++) {
79     int ok = 1;
80     for (int i = 0; i < (int)g[u].size(); i++) {
81       int v = g[u][i];
82       if (v == fa[u]) {
83         if (n - sz[u] - up[u] > n / 2) ok = 0;
84       }
85       else {
86         if (sz[v] - down[v] > n / 2) ok = 0;
87       }
88     }
89     printf("%d ", ok);
90   }
91   puts("");
92   return 0;
93 }

代码君

时间: 2024-08-07 21:16:55

AIM Tech Round 3 (Div. 2)的相关文章

AIM Tech Round 3 (Div. 2) B

Description Vasya takes part in the orienteering competition. There are n checkpoints located along the line at coordinates x1, x2, ..., xn. Vasya starts at the point with coordinate a. His goal is to visit at least n - 1 checkpoint in order to finis

AIM Tech Round 3 (Div. 2) E. Centroids

题解: 树形dp 非常好的一道题目 题意: 对于每个点.更改一条边,能否使得这个点成为树的重心 题解: 所谓重心:指去掉这个点后,最大的连通分量的点数<=n/2 对于每个点,分为向下分析,向上分析 向下分析:找寻点u的子节点的最大节点v.然后找寻节点v的子节点的小于等于n/2的最大子节点,连接到u上 向上分析:找寻点u的父节点的最大节点v.如果v==u那么.找寻次大节点w.然后找寻该点的子节点的小于等于n/2的最大子节点,连接到u上 向下分析和向上分析只需要判断一个,因为大于n/2的点只有一个

AIM Tech Round 4 (Div. 2)

A题 分析:暴力 1 #include "iostream" 2 #include "cstdio" 3 #include "cstring" 4 #include "string" 5 using namespace std; 6 const int maxn=100+10; 7 int vis[maxn],n; 8 string s; 9 int main() 10 { 11 cin>>s; 12 cin>

AIM Tech Round 4 (Div. 2) A B C

A. Diversity 题意:给出一个字符串,和n,问最多改变多少个字符,使其不同字符最少为n 1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int N=1e5+10; 5 6 map<char ,int >ma; 7 int main(){ 8 string s; 9 cin>>s; 10 int n; 11 cin>>n; 12 int

AIM Tech Round 4 (Div. 2)(A,暴力,B,组合数,C,STL+排序)

A. Diversity time limit per test:1 second memory limit per test:256 megabytes input:standard input output:standard output Calculate the minimum number of characters you need to change in the string s, so that it contains at least k different letters,

【AIM Tech Round 4 (Div. 2) D Prob】

·题目:D. Interactive LowerBound ·英文题,述大意:       有一个长度为n(n<=50000)的单链表,里面的元素是递增的.链表存储在一个数组里面,给出长度n.表头在数组的下标和一个值w.题目要求求出链表中大于等于w值的元素中的最小元素.注意,这道题是一道interactive.由于链表是未知的,最多可以进行1999个询问,询问形式:?i.表示询问数组下标为i,询问后,会得到一个答案组(val,Next),表示询问的元素是val,链表下一位所在的数组下标是Next

codeforces708b// Recover the String //AIM Tech Round 3 (Div. 1)

题意:有一个01组成的串,告知所有长度为2的子序列中,即00,01,10,11,的个数a,b,c,d.输出一种可能的串. 先求串中0,1的数目x,y. 首先,如果00的个数a不是0的话,设串中有x个0,C(X,2)=a,那么x*(x+1)=2a,解方程(其实只要看sqrt(x)*(sqrt(x)+1)等不等于2a),x没有整数解就IMPOSSIBLE.同理得出1的个数y.如果00个数是0看01个数. 第二,如果x*y!=b+c则IMPOSSIBLE,具体自己举个例子就明白. 最后,先将所有的0组

AIM Tech Round (Div. 2)

A. Save Luke 题意:给一个人的长度d,然后给一个区间长度0~L,给你两个子弹的速度v1,v2,两颗子弹从0和L向中间射去(其实不是子弹,是一种电影里面那种绞牙机之类的东西就是一个人被困在里面了,两边有着那种尖刺的墙向中间靠拢的那种)问Luke能存活的最长时间 思路:看代码吧,简单易懂 1 #include<cstdio> 2 #include<cmath> 3 int main() 4 { 5 int d,l,v1,v2; 6 while(scanf("%d%

【AIM Tech Round 5 (rated, Div. 1 + Div. 2) A】 Find Square

[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 找到左上角.往下一直走,往右一直走走到B边界就好. 中点的话.直接输出中位数 [代码] #include <bits/stdc++.h> #define LL long long #define rep1(i,a,b) for (int i = a;i <= b;i++) #define rep2(i,a,b) for (int i = a;i >= b;i--) #define all(x) x.begin(),