AIM Tech Round 3 (Div. 2) ABCDE题解
来源:互联网 发布:淘宝怎么改会员名字 编辑:程序博客网 时间:2024/05/29 08:05
A. Juicer
水题。模拟放橙子的过程,大于尺寸直接跳过。刚开始没太读懂题意,以为是当将要溢出的时候清空,实际上是溢出以后再清空。
#include <map>#include <set>#include <cmath>#include <ctime>#include <queue>#include <stack>#include <string>#include <vector>#include <cstdio>#include <cstring>#include <cstdlib>#include <iostream>#include <algorithm>using namespace std;typedef __int64 LL;typedef pair<int,int> PII;#define FIN freopen("in.txt", "r", stdin);#define FOUT freopen("out.txt", "w", stdout);#define lson l, mid, cur << 1#define rson mid + 1, r, cur << 1 | 1#define bitcnt(x) __builtin_popcount(x)#define bitcntll(x) __builtin_popcountll(x)//#pragma comment(linker, "/STACK:1024000000,1024000000")const int INF = 0x3f3f3f3f;const LL INFLL = 0x3f3f3f3f3f3f3f3fLL;const double ERR = 1e-8;const int MOD = 1e6 + 3;const int MAXN = 1e6 + 50;const int MAXM = 2e5 + 50;int n, b, d, a[MAXN];int main() {#ifdef LOCAL_NORTH FIN;#endif // LOCAL_NORTH while (~scanf("%d%d%d", &n, &b, &d)) { int cnt = 0, tot = 0; for (int i = 0; i < n; i++ ) { scanf("%d", &a[i]); if (a[i] > b) continue; if (tot + a[i] > d) { cnt++; tot = 0; } else { tot += a[i]; } } printf("%d\n", cnt); }#ifdef LOCAL_NORTH cout << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC * 1000 << " ms." << endl;#endif // LOCAL_NORTH return 0;}
B. Checkpoints
暴力。输入的时候计算出所有点的坐标减去初始点的坐标,然后排序。显然访问连续n-1个点要走的总距离最小,所以枚举左端点i,计算出右端点i+n-2,计算出初始点访问[i,i+n-2]需要走的距离。(后来才想起来只可能走[1,n-1]和[2,n]两个区间,枚举都不用了。。。
#include <map>#include <set>#include <cmath>#include <ctime>#include <queue>#include <stack>#include <string>#include <vector>#include <cstdio>#include <cstring>#include <cstdlib>#include <iostream>#include <algorithm>using namespace std;typedef __int64 LL;typedef pair<int,int> PII;#define FIN freopen("in.txt", "r", stdin);#define FOUT freopen("out.txt", "w", stdout);#define lson l, mid, cur << 1#define rson mid + 1, r, cur << 1 | 1#define bitcnt(x) __builtin_popcount(x)#define bitcntll(x) __builtin_popcountll(x)//#pragma comment(linker, "/STACK:1024000000,1024000000")const int INF = 0x3f3f3f3f;const LL INFLL = 0x3f3f3f3f3f3f3f3fLL;const double ERR = 1e-8;const int MOD = 1e6 + 3;const int MAXN = 1e6 + 50;const int MAXM = 2e5 + 50;int n, a, loc[MAXN];int main() {#ifdef LOCAL_NORTH FIN;#endif // LOCAL_NORTH while (~scanf("%d%d", &n, &a)) { for (int i = 0; i < n; i++) { scanf("%d\n", &loc[i]); loc[i] -= a; } sort(loc, loc + n); LL dis = INFLL; for (int i = 0; i + n - 2 < n; i++) { if (loc[i] <= 0 && loc[i + n - 2] <= 0) { //当左右端点都在初始点左边 dis = min(dis, (LL)-loc[i]); } else if (loc[i] <= 0 && loc[i + n - 2] >= 0) { //在左右两边 dis = min(dis, (LL)min(-loc[i] * 2 + loc[i + n - 2], -loc[i] + loc[i + n - 2] * 2)); //注意要返回,所以乘2 } else if (loc[i] >= 0 && loc[i + n - 2] >= 0) { //都在初始点右边 dis = min(dis, (LL)loc[i + n - 2]); } } printf("%I64d\n", dis); }#ifdef LOCAL_NORTH cout << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC * 1000 << " ms." << endl;#endif // LOCAL_NORTH return 0;}
C. Letters Cyclic Shift
既然要去字典序最小,那么显然是变换一个不包含a的连续区间,直接搞就可以了。注意题目要求至少变换一个字符,所以当字符串全是a时,要把最后一位的a变为z。
#include <map>#include <set>#include <cmath>#include <ctime>#include <queue>#include <stack>#include <string>#include <vector>#include <cstdio>#include <cstring>#include <cstdlib>#include <iostream>#include <algorithm>using namespace std;typedef __int64 LL;typedef pair<int,int> PII;#define FIN freopen("in.txt", "r", stdin);#define FOUT freopen("out.txt", "w", stdout);#define lson l, mid, cur << 1#define rson mid + 1, r, cur << 1 | 1#define bitcnt(x) __builtin_popcount(x)#define bitcntll(x) __builtin_popcountll(x)//#pragma comment(linker, "/STACK:1024000000,1024000000")const int INF = 0x3f3f3f3f;const LL INFLL = 0x3f3f3f3f3f3f3f3fLL;const double ERR = 1e-8;const int MOD = 1e6 + 3;const int MAXN = 1e6 + 50;const int MAXM = 2e5 + 50;string s;int main() {#ifdef LOCAL_NORTH FIN;#endif // LOCAL_NORTH while (cin >> s) { int len = s.size(); bool ok = true; for (int i = 0; i < len; i++) { if (ok && s[i] == 'a') continue; if (s[i] != 'a') { s[i]--; ok = false; } else break; } if (ok) s[len - 1] = 'z'; cout << s << endl; }#ifdef LOCAL_NORTH cout << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC * 1000 << " ms." << endl;#endif // LOCAL_NORTH return 0;}
D. Recover the String
这道题有毒- -
代码写的太乱了,我自己都不想看,说一些思路吧。
题目给出了4个数分别表示原字符串的长度为2的子序列(注意不是子串,不需要连续)的个数,要求还原出字符串。
首先,可以通过a00和a11计算出字符串的0和1的数量(当然计算出的n和m不是整数,就一定是Impossible了),然后就是把n个0和m个1排列组合。
我们可以这样考虑,长度为n,只包含0的字符串,每次插入一个1,那么每次增加的“01”子序列和“10”子序列的总和数一定是n。所以(a01+a10)%n!=0的情况也一定是Impossible。
所以还原字符串就是把1不断地插入到字符串里面。插入的过程就是所有的1都插入到所有的0后面,每插入1个1,“01”子序列的数量就增加n,如果a01%n!=0,那么还需要一个1插入到第(a01%n)个0后面。多余的1全部插入到所有的0前面。
然后就是大量的特判。。。
代码太挫不要看。
#include <map>#include <set>#include <cmath>#include <ctime>#include <queue>#include <stack>#include <string>#include <vector>#include <cstdio>#include <cstring>#include <cstdlib>#include <iostream>#include <algorithm>using namespace std;typedef __int64 LL;typedef pair<int,int> PII;#define FIN freopen("in.txt", "r", stdin);#define FOUT freopen("out.txt", "w", stdout);#define lson l, mid, cur << 1#define rson mid + 1, r, cur << 1 | 1#define bitcnt(x) __builtin_popcount(x)#define bitcntll(x) __builtin_popcountll(x)//#pragma comment(linker, "/STACK:1024000000,1024000000")const int INF = 0x3f3f3f3f;const LL INFLL = 0x3f3f3f3f3f3f3f3fLL;const double ERR = 1e-8;const int MOD = 1e6 + 3;const int MAXN = 1e6 + 50;const int MAXM = 2e5 + 50;LL a00, a01, a10, a11;int main() {#ifdef LOCAL_NORTH FIN;#endif // LOCAL_NORTH while (~scanf("%I64d%I64d%I64d%I64d", &a00, &a01, &a10, &a11)) { LL zero, one; if (a00 + a01 + a10 + a11 == 0) { printf("1\n"); continue; } if (!a00 || !a11) { if (!a00 && !a11) { if ((!a01 && !a10) || (a01 && a10)) { printf("Impossible\n"); } else if (a01 <= 1 && !a10) { printf("01\n"); } else if (!a01 && a10 <= 1) { printf("10\n"); } else { printf("Impossible\n"); } } else if (!a00) { double t = (1 + sqrt(1 + 8 * a11)) / 2; if (fabs(t - floor(t)) > ERR) { printf("Impossible\n"); continue; } one = (LL)t; if (a01 + a10) { if (a10 + a01 != one) { printf("Impossible\n"); } else { for (LL i = 0; i < one; i++) { if (i == a10) printf("0"); printf("1"); } if (one == a10) // 0 0 4 6 printf("0"); puts(""); } } else { for (LL i = 0; i < one; i++) printf("1"); puts(""); } } else { double t = (1 + sqrt(1 + 8 * a00)) / 2; if (fabs(t - floor(t)) > ERR) { printf("Impossible\n"); continue; } zero = (LL)t; if (a01 + a10) { if (a01 + a10 != zero) { printf("Impossible\n"); } else { for (LL i = 0; i < zero; i++) { if (i == a01) printf("1"); printf("0"); } if (zero == a01) // 6 4 0 0 printf("1"); puts(""); } } else { for (LL i = 0; i < zero; i++) printf("0"); puts(""); } } continue; } double t = (1 + sqrt(1 + 8 * a00)) / 2; if (fabs(t - floor(t)) > ERR) { printf("Impossible\n"); continue; } zero = (LL)t; t = (1 + sqrt(1 + 8 * a11)) / 2; if (fabs(t - floor(t)) > ERR) { printf("Impossible\n"); continue; } one = (LL)t; if ((a01 + a10 == 0) || (a10 + a01) % max(zero, one) || (a01 + a10 > zero * one)) { printf("Impossible\n"); continue; } LL rear, pos = -1, head; if (zero > one) { rear = min(one, a01 / zero); if (a01 % zero) pos = a01 % zero; head = one - rear - (pos == -1 ? 0 : 1); for (LL i = 0; i < head; i++) printf("1"); for (LL i = 0; i < zero; i++) { printf("0"); if (pos != -1 && i == pos - 1) printf("1"); } for (LL i = 0; i < rear; i++) printf("1"); } else { rear = min(zero, a10 / one); if (a10 % one) pos = a10 % one; head = zero - rear - (pos == -1 ? 0 : 1); for (LL i = 0; i < head; i++) printf("0"); for (LL i = 0; i < one; i++) { printf("1"); if (pos != -1 && i == pos - 1) printf("0"); } for (LL i = 0; i < rear; i++) printf("0"); } puts(""); }#ifdef LOCAL_NORTH cout << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC * 1000 << " ms." << endl;#endif // LOCAL_NORTH return 0;}
E. Centroids
树形dp。
题目要求判断树上的每一个点,能不能通过至多一次的拆一条边再建一条边(添加之后还是一棵树)操作,使其成为树的重心(树的重心的定义是:以该点为树根,每棵子树的大小都不超过节点数的一半)。
对于一个不是树的重心的节点v,要怎么样操作才能使它成为新树的重心呢?很明显需要在v的节点数大于n/2的子树中,找到一个最大的不超过n/2的子树,把该子树连到v上。这种情况一定是最优的。如果经过一次这样的操作,还有子树大于n/2,那么节点v就要输出0。
所以对于节点v,只需要求出与v相连的子树(v的父节点的不同,详见图E-1)的最大的不超过n/2的子树的大小。具体过程就是3遍dfs。
第一遍dfs,求出每棵子树的大小。
第二遍dfs,求出每棵子树的最大不超过n/2的子树的大小。
第三遍dfs,对于节点v,求出v的父节点pre的不经过v的最大不超过n/2的子树的大小。
(第二、三遍dfs的过程类似于求树的直径,都是利用上一次dfs的结果,来求出v与整棵树的节点的关系)
最后,只需要从1到n枚举v,只要有一棵子树不满足条件,节点v就要输出0(可以理解成:无论怎么拆边与重连,v的某些子树大小都大于n/2)。
#include <map>#include <set>#include <cmath>#include <ctime>#include <queue>#include <stack>#include <string>#include <vector>#include <cstdio>#include <cstring>#include <cstdlib>#include <iostream>#include <algorithm>using namespace std;typedef __int64 LL;typedef pair<int,int> PII;#define FIN freopen("in.txt", "r", stdin);#define FOUT freopen("out.txt", "w", stdout);#define lson l, mid, cur << 1#define rson mid + 1, r, cur << 1 | 1#define bitcnt(x) __builtin_popcount(x)#define bitcntll(x) __builtin_popcountll(x)//#pragma comment(linker, "/STACK:1024000000,1024000000")const int INF = 0x3f3f3f3f;const LL INFLL = 0x3f3f3f3f3f3f3f3fLL;const double ERR = 1e-8;const int MOD = 1e6 + 3;const int MAXN = 4e5 + 50;const int MAXM = 2e5 + 50;int n;struct Edge { int v, nxt;} E[MAXN << 1];int Head[MAXN], tot;void edge_init() { tot = 0; memset(Head, -1, sizeof(Head));}void edge_add(int u, int v) { E[tot].v = v; E[tot].nxt = Head[u]; Head[u] = tot++;}int son[MAXN], son_max[MAXN], fa_max[MAXN], par[MAXN];void dfs(int u, int pre) { son[u] = 1; par[u] = pre; for (int i = Head[u]; ~i; i = E[i].nxt) { int v = E[i].v; if (v == pre) continue; dfs(v, u); son[u] += son[v]; }}void dfs_down(int u, int pre) { son_max[u] = (son[u] <= n / 2) ? son[u] : 0; for (int i = Head[u]; ~i; i = E[i].nxt) { int v = E[i].v; if (v == pre) continue; dfs_down(v, u); son_max[u] = max(son_max[u], son_max[v]); }}void dfs_up(int u, int t, int pre) { fa_max[u] = max(((n - son[u] <= n / 2) ? (n - son[u]) : 0), t); int max1 = 0, max2 = 0; //最大值与次大值 for (int i = Head[u]; ~i; i = E[i].nxt) { int v = E[i].v; if (v == pre) continue; int tmp = son_max[v]; if (tmp >= max1) swap(max1, tmp); if (tmp >= max2) swap(max2, tmp); } for (int i = Head[u]; ~i; i = E[i].nxt) { int v = E[i].v; if (v == pre) continue; if (max1 == son_max[v]) //v的子树与max所记录的子树不是同一棵 dfs_up(v, max(fa_max[u], max2), u); else dfs_up(v, max(fa_max[u], max1), u); }}int main() {#ifdef LOCAL_NORTH FIN;#endif // LOCAL_NORTH while (~scanf("%d", &n)) { edge_init(); for (int i = 0; i < n - 1; i++) { int u, v; scanf("%d%d", &u, &v); edge_add(u, v); edge_add(v, u); } dfs(1, 0); dfs_down(1, 0); dfs_up(1, 0, 0); for (int u = 1; u <= n; u++) { bool ok = true; for (int i = Head[u]; ~i; i = E[i].nxt) { int v = E[i].v; if (v == par[u]) { if (n - son[u] - fa_max[u] > n / 2) { ok = false; break; } } else { if (son[v] - son_max[v] > n / 2) { ok = false; break; } } } printf("%d%c", ok ? 1 : 0, " \n"[u == n]); } }#ifdef LOCAL_NORTH cout << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC * 1000 << " ms." << endl;#endif // LOCAL_NORTH return 0;}
- AIM Tech Round 3 (Div. 2) ABCDE题解
- AIM Tech Round (Div. 2)题解
- Codeforces AIM Tech Round (Div. 2) 题解
- AIM Tech Round 3 (Div. 2)(题解)
- AIM Tech Round 3 (Div. 2)
- AIM Tech Round 3 (Div. 2)
- AIM Tech Round 3 (Div. 2)
- 【codeforces】AIM Tech Round 3 (Div. 2)
- codeforces AIM Tech Round 3 (Div. 2)
- Codeforces AIM TECH Round 4 (Div 2) 题解 (ABCD)
- AIM Tech Round 4 (Div. 2) B, C 题解
- AIM Tech Round 3 (Div. 2) A.Juicer
- AIM Tech Round 3 (Div. 2) C.Letters Cyclic Shift
- AIM Tech Round 3 (Div. 2) B. Checkpoints
- codeforces AIM Tech Round 3 (Div. 2) B. Checkpoints
- AIM Tech Round 3 (Div. 2) C(贪心)
- CodeForces AIM Tech Round 3 (Div. 2) D
- codeforces AIM Tech Round 3 (Div. 2) (A~D)
- 06,缓冲区
- MySQL触发器
- CentOS服务器安全设置
- Ubuntu, Debian, Kali, CentOS等linux重置root密码
- Android异步消息处理机制详解
- AIM Tech Round 3 (Div. 2) ABCDE题解
- 不使用算数运算符 完成两数求和
- COM组件开发(一)—— 对象与接口 .
- CSS中position定位
- maven创建web工程第一次使用jetty运行报错
- 07,数组
- 月薪3万的程序员都避开了哪些坑?
- tomcat context.xml文件配置<Loader delegate="true" />作用
- ObjectFactory采用单列模式设置工厂模式