CC XENTASK

由于要交替选,所以要不第一个人选位置为奇数的数,第二个人选位置为偶数的数,要不第一个人选位置为偶数的数,第二个人选位置为奇数的数。取最小值即可。

#include <cstring>
#include <cstdio>
#include <algorithm>using namespace std;int n, sum[2][2];void solve() {memset(sum, 0, sizeof sum);scanf("%d", &n);for (int i = 0; i < 2; i ++)for (int j = 1; j <= n; j ++) {int x;scanf("%d", &x);sum[i][j & 1] += x; }printf("%d\n", min(sum[0][0] + sum[1][1], sum[0][1] + sum[1][0]));
}int main() {int t;scanf("%d", &t);for (int i = 1; i <= t; i ++) solve();
}

CC EXTRAN

假设原数列最小的数是l,最大的数是r。加入的数只有两种情况,一种是加入了一个在l到r,这个直接判断有没有重复出现的数即可。第二种是加入了一个小于l-1,或大于r+1的数,对于这种情况只需要存下读入数据中最小和最大的数,如果最小的数加1出现在了读入数据中,则最大的数是答案,否则最小的数就是答案。

#include <cstring>
#include <cstdio>
#include <algorithm>
#include <map>using namespace std;const int Inf = 1e9 + 7;int n, ans;
map<int,int> ref;void solve(int id) {ans = 0;int mn = Inf, mx = 0;scanf("%d", &n);for (int i = 1; i <= n; i ++) {int x;scanf("%d", &x);if (ref[x] == id) ans = x; elseref[x] = id;mn = min(mn, x);mx = max(mx, x);}if (ans) printf("%d\n", ans); else {if (ref[mn + 1] == id) printf("%d\n", mx); elseprintf("%d\n", mn);}
}int main() {int t;scanf("%d", &t);for (int i = 1; i <= t; i ++) solve(i);
}

CC BANDMATR

其实可以交换任意多次就是让你把0不断加入到矩阵中,为了尽量使k下,不难发现,我们应该尽量矩阵的右上角和左下角放数字。每当k减1就会多出两行斜着的1需要加入0。我们可以斜着一行一行枚举,判断当前剩下的0是否够填满这些格子。如过可以,继续判断下一行,否则当前k已经是最优解。

#include <cstring>
#include <cstdio>
#include <algorithm>using namespace std;int n;void solve() {int num = 0;scanf("%d", &n);for (int i = 1; i <= n; i ++)for (int j = 1; j <= n; j ++) {int x;scanf("%d", &x);if (x == 0) num ++;}int ans = n - 1;for (int i = 1; i <= n - 1; i ++)if (num >= i * (i + 1)) ans --; elsebreak;printf("%d\n", ans);
}int main() {int t;scanf("%d", &t);for (int i = 1; i <= t; i ++) solve();
}

CC SCHEDULE

首先预处理出a[i]表示第i段连续相同的长度是多少。那么我们可以考虑二分答案lim,然后判断是否合法。对于连续一段相同的,考虑不改变最左边和最右边的数,使当前段不会影响到相邻的段。那么我们每隔lim个数就改变一个数字,假如要改变最后一个数字,就变成改变倒数第二个数字以保证不改变最右边的数,这样一段需要改变的数字就是a[i]/(lim+1),判断一个总共改变数字的个数与k的关系即可。但是当lim=1时不能保证不改变最左和最右的数,那么特判一下即可。

#include <cstring>
#include <cstdio>
#include <algorithm>using namespace std;const int MAXN = 1e6 + 5;int n, m, k, a[MAXN];
char s[MAXN];bool chk(int lim) {int num = 0;for (int i = 1; i <= m; i ++)num += a[i] / (lim + 1);return num <= k;
}bool chk() {int num = 0;for (int i = 1; i <= n; i ++)if (s[i] - '0' == (i & 1)) num ++;return num <= k || (n - num) <= k;
}void solve() {scanf("%d%d", &n, &k);scanf("%s", s + 1);m = 1, a[1] = 1;for (int i = 1; i <= n; i ++) {if (s[i] == s[i - 1]) a[m] ++; elsea[++ m] = 1;}if (chk()) {printf("1\n");return;}int l = 2, r = n, ans;while (l <= r) {int mid = (l + r) >> 1;if (chk(mid)) r = mid - 1, ans = mid; elsel = mid + 1;}printf("%d\n", ans);
}int main() {int t;scanf("%d", &t);for (int i = 1; i <= t; i ++) solve();
}

CC PSHTBRTH

由于矩阵大小只有4*4,所以可以预处理出所有矩阵的sg值。这个只需依次枚举每个矩阵,然后枚举删掉的矩阵,mex起来,复杂度是 O(216∗44) O(2^{16}*4^4)。现在只要把询问的一段区间矩阵的sg值异或起来就是答案,这个可以用树状数组轻松维护。

#include <cstring>
#include <algorithm>
#include <cstdio>using namespace std;const int MAXS = (1 << 16);
const int MAXN = 1e5 + 5;char s[10];
int sg[MAXS], flag[257], sta[4][4][4][4];
int n, m, a[MAXN], tr[MAXN];void prepare() {for (int x1 = 0; x1 < 4; x1 ++)for (int x2 = x1; x2 < 4; x2 ++)for (int y1 = 0; y1 < 4; y1 ++)for (int y2 = y1; y2 < 4; y2 ++)for (int x = x1; x <= x2; x ++)for (int y = y1; y <= y2; y ++) sta[x1][y1][x2][y2] += (1 << (4 * x + y));sg[0] = 0;for (int s = 1; s < MAXS; s ++) {memset(flag, 0, sizeof flag);for (int x1 = 0; x1 < 4; x1 ++)for (int x2 = x1; x2 < 4; x2 ++)for (int y1 = 0; y1 < 4; y1 ++)for (int y2 = y1; y2 < 4; y2 ++) {int num = sta[x1][y1][x2][y2];if ((s & num) == num)flag[sg[s - num]] = 1;}for (sg[s] = 0; flag[sg[s]]; sg[s] ++);}
}int get() {int now = 0;for (int x = 0; x < 4; x ++) {scanf("%s", s);for (int y = 0; y < 4; y ++) if (s[y] == '1')now += (1 << (x * 4 + y));  }return sg[now];
}void modify(int s, int val) {for (; s <= n; s += (s & -s)) tr[s] ^= val;
}int query(int s) {int ans = 0;for (; s; s -= (s & -s)) ans ^= tr[s];return ans;
}void solve() {scanf("%d%d", &n, &m);for (int i = 1; i <= n; i ++) {a[i] = get();modify(i, a[i]);}for (int i = 1; i <= m; i ++) {int ord, l, r, x;scanf("%d", &ord);if (ord == 1) {scanf("%d%d", &l, &r);printf((query(r) ^ query(l - 1)) ? "Pishty\n" : "Lotsy\n");} else {scanf("%d", &x);modify(x, a[x]);a[x] = get();modify(x, a[x]);}}for (int i = 1; i <= n; i ++) modify(i, a[i]);
}int main() {prepare();int t;scanf("%d", &t);for (int i = 1; i <= t; i ++) solve();
}

CC FAVGAME

设状态f[i][j]表示以i为根的子树当第一天在j小时开始时的最少花多少天,g[i][j]表示以i为根的子树当第一天在j小时开始花多少天同时那一天最少用多少小时。这样对于每个节点,我们可以用一个数位dp转移,ff[s]表示当儿子完成情况的二进制状态为时,最少花费的天数,gg[s]当儿子完成情况的二进制状态为时花费最少天数的同时最小,那一天最少需要用多少小时。暴力转移一下,复杂度是 O(n∗2m∗m∗h) O(n*2^m*m*h),由于2^m肯定不满,所以是可以过的。

#include <cstring>
#include <cstdio>
#include <algorithm>
#define min(a, b) ((a < b) ? a : b)using namespace std;const int MAXN = 1e3 + 5, MAXM = (1 << 10) + 5;
const int Inf = 1e9;int n, h, t[MAXN], son[MAXN][15], num[MAXN];
int f[MAXN][30], g[MAXN][30], ff[MAXM], gg[MAXM]; void dfs(int now) {for (int i = 1; i <= num[now]; i ++) dfs(son[now][i]);int m = (1 << num[now]) - 1;bool flag = 0;for (int tim = 0; tim < h; tim ++) {if (t[now] + tim <= h) ff[0] = 1, gg[0] = t[now] + tim; elseff[0] = 2, gg[0] = t[now], flag = 1;for (int s = 1; s <= m; s ++) {ff[s] = Inf;for (int i = 1; i <= num[now]; i ++) {if (!(s & (1 << (i - 1)))) continue;int ls = s ^ (1 << (i - 1)), nt = son[now][i];int nd = ff[ls] + f[nt][gg[ls]] - (gg[ls] < h);if (nd < ff[s]) {ff[s] = nd;gg[s] = g[nt][gg[ls]];} else if (nd == ff[s]) gg[s] = min(gg[s], g[nt][gg[ls]]);}}if (flag) {for (int i = tim; i < h; i ++)f[now][i] = ff[m], g[now][i] = gg[m];break;}f[now][tim] = ff[m], g[now][tim] = gg[m];}f[now][h] = f[now][0], g[now][h] = g[now][0];
}void solve() {scanf("%d%d", &n, &h);for (int i = 1; i <= n; i ++) scanf("%d", &t[i]);for (int i = 1; i <= n; i ++) {scanf("%d", &num[i]);for (int j = 1; j <= num[i]; j ++) scanf("%d", &son[i][j]);}dfs(1);printf("%d\n", f[1][0]);
}int main() {int t;scanf("%d", &t);for (int i = 1; i <= t; i ++) solve();
}

CC SUMDIS

把起始点i从右到左枚举,假如是暴力的做法,可以从i+1枚举到n,得出每个点的最短路。这样复杂度肯定是O(n^2)的。假如一个点在起始点为i+1,i+2和i+3时都可以通过一个点转移过来,那么这个点之后就都可以视为由这个点转移过来,这还是比较显然的。那么我们把这些点和它的转移点并查集起来,因为它们的路径大部分是相同的,所以只需把它到转移点的路径长度等信息放到转移点上一起考虑就可以了。复杂度,玄学…

#include <cstring>
#include <cstdio>
#include <algorithm>using namespace std;
typedef long long LL;const int MAXN = 1e5 + 5;
const int Inf = 1e9 + 7;int n, num, d[MAXN], fr[MAXN][3], path[MAXN][4], nxt[MAXN], st, ed;
int tot[MAXN], disf[MAXN], dis[MAXN], fa[MAXN];
LL sub[MAXN];
bool flag[MAXN];void get_useful() {while (flag[st]) st = nxt[st];d[num = 1] = ed = st;for (int now = nxt[st]; now; ed = now, now = nxt[now]) if (!flag[now]) nxt[ed] = d[++ num] = now;nxt[ed] = 0;reverse(d + 1, d + num + 1);for (int i = 1; i <= num; i ++) dis[d[i]] = Inf;
}int get(int now) {if (fa[now] == now) return now;int tmp = fa[now];fa[now] = get(fa[now]);disf[now] += disf[tmp];return fa[now];
}void solve() {scanf("%d", &n);for (int i = 1; i <= 3; i ++)for (int j = 1; j <= n - i; j ++) scanf("%d", &path[j][i]);LL ans = 0;for (int i = 1; i <= n; i ++) {fa[i] = i, tot[i] = 1;dis[i] = disf[i] = sub[i] = nxt[i] = flag[i] = 0;for (int j = 0; j < 3; j ++) fr[i][j] = 0;}st = n;for (int i = n - 1; i; i --) {get_useful();int id = i % 3;for (int j = 1; j <= num; j ++) {int now = d[j];for (int k = max(i, now - 3); k <= now - 1; k ++) {int ds = dis[get(k)] + disf[k] + path[k][now - k];if (ds < dis[now]) {dis[now] = ds;fr[now][id] = k;} else if (ds == dis[now]) fr[now][id] = min(fr[now][id], k);}ans += 1ll * tot[now] * dis[now] + sub[now];int tmp = fr[now][0];if (!tmp || fr[now][1] != tmp || fr[now][2] != tmp) continue;int fx = get(tmp);fa[now] = fx, disf[now] = disf[tmp] + path[tmp][now - tmp];sub[fx] += sub[now] + 1ll * disf[now] * tot[now];tot[fx] += tot[now];flag[now] = 1;}nxt[ed] = i;}printf("%lld\n", ans);
}int main() {int t;scanf("%d", &t);for (int i = 1; i <= t; i ++) solve();
}

CC BEARTRAP

手玩题,首先可以手玩出一种方案,主要思想是我们可以通过一些点的摆放固定猫在后面几步的走向,然后提前造一个笼子来包住它。然后就是找一种好的打法。

这个图,可以用画图打开,然后用油漆桶手玩!!!!

#include <cstring>
#include <cstdio>
#include <algorithm>using namespace std;struct Coor {int x, y;Coor (int a, int b) {x = a, y = b;}Coor () {}
};const Coor fx[6] = {Coor(-1, 0), Coor(0, -1), Coor(1, -1), Coor(-1, 1), Coor(0, 1), Coor(1, 0)};char s[100];
Coor cat[100], block[100];
bool ok;Coor operator - (Coor a, Coor b) {return Coor(a.x - b.x, a.y - b.y);}
Coor operator + (Coor a, Coor b) {return Coor(a.x + b.x, a.y + b.y);}
Coor operator * (Coor a, int p) {return Coor(a.x * p, a.y * p);}
Coor operator / (Coor a, int p) {return Coor(a.x / p, a.y / p);}
bool operator == (Coor a, Coor b) {return a.x == b.x && a.y == b.y;}bool chk_around(Coor a, Coor b) {for (int i = 0; i < 6; i ++) if ((a + fx[i]) == b) return 1;return 0;
}void solve() {ok = 0;for (int i = 1; i <= 11; i ++) {scanf("%s", s + 1);if (s[1] == 'W') return;scanf("%d%d", &cat[i].x, &cat[i].y);switch (i) {case 1: block[1] = cat[1] * 2;case 2: block[2] = cat[2] * 2;case 3: block[3] = block[2] + (cat[3] - cat[2]) * 3;case 4: block[4] = block[2] - cat[4] + block[3];case 5: block[5] = (cat[5] - cat[4]) * 3 + cat[5];case 6: {int around = (chk_around(cat[6], block[3])) ? 3 : 4;int far = (around == 3) ? 4 : 3;block[6] = block[far] - cat[6] + block[around];}case 7: block[7] = cat[7] + cat[2];case 8: block[8] = cat[8] - cat[7] + cat[8];case 9: block[9] = block[8] - block[7] + block[8];case 10: block[10] = cat[7];case 11: block[11] = cat[10];}printf("BLOCK %d %d\n", block[i].x, block[i].y);fflush(stdout);}scanf("%s", s);
}int main() {int t, m;scanf("%d%d", &t, &m);for (int i = 1; i <= t; i ++) solve();
}

CC TUPLES2

直接把两部分的答案分别求出来想加,对于三条路径没交的情况,设状态f[i][j][k][s]表示做到i节点的子树,选了j条路径,k条伸出i,i是否已经被一条路覆盖,我们只需要讨论一下两条路径是否会在节点i相交变成一条,然后就是经典的树形dp了。对于三条路径必须有叫的情况。我们可以枚举深度最小的三条路径的交点x,然后枚举一下有多少条路径在x的子树内,多少条有部分在子树外,分别统计一下个数乘起来。

#include <cstring>
#include <cstdio>
#include <algorithm>using namespace std;const int MAXN = 3e5 + 5;
const int Mo = 1e9 + 7;int ans, n, all, inv[11], size[MAXN];
int f[MAXN][4][2][2], t[4][2][2];
int tot, Last[MAXN], Next[MAXN * 2], Go[MAXN * 2];void link(int u, int v) {Next[++ tot] = Last[u], Last[u] = tot, Go[tot] = v;
}int C(int n, int m) {int ans = 1;for (int i = 0; i < m; i ++) ans = 1ll * ans * (n - i) % Mo;return 1ll * ans * inv[m] % Mo;
}int pow(int x, int y) {int ans = 1;for (; y; y >>= 1, x = 1ll * x * x % Mo)if (y & 1) ans = 1ll * ans * x % Mo;return ans;
}void dfs(int now, int pre) {f[now][0][0][0] = 1;f[now][0][1][0] = 1;for (int p = Last[now]; p; p = Next[p]) {int v = Go[p];if (v == pre) continue;dfs(v, now);memset(t, 0, sizeof t);for (int j1 = 3; j1 + 1; j1 --)for (int k1 = 0; k1 < 2; k1 ++)for (int l1 = 0; l1 < 2; l1 ++) {if (!f[now][j1][k1][l1]) continue;for (int j2 = 0; j2 < 4 - j1; j2 ++)for (int k2 = 0; k2 < 2; k2 ++)for (int l2 = 0; l2 < 2; l2 ++) {if (!f[v][j2][k2][l2] || (k2 == 1 && l1)) continue;int j3 = j1 + j2, k3 = k1 | k2, l3 = l1;if (k1 == 1 && k2 == 1) j3 ++, k3 = 0, l3 = 1;if (j3 < 4) (t[j3][k3][l3] += 1ll * f[now][j1][k1][l1] * f[v][j2][k2][l2] % Mo) %= Mo; }}memcpy(f[now], t, sizeof t);}
}void dfs2(int now, int pre) {size[now] = 1; int all = 0;for (int p = Last[now]; p; p = Next[p]) {int v = Go[p];if (v == pre) continue;dfs2(v, now);all = (all + 1ll * size[v] * size[now] % Mo) % Mo;size[now] += size[v];}for (int i = 0; i < 3; i ++)ans = (ans + 1ll * C(1ll * size[now] * (n - size[now]) % Mo, i) * C(all, 3 - i) % Mo) % Mo;
}int main() {inv[0] = 1;for (int i = 1; i <= 10; i ++) inv[i] = 1ll * inv[i - 1] * pow(i, Mo - 2) % Mo;scanf("%d", &n);for (int i = 1; i < n; i ++) {int u, v;scanf("%d%d", &u, &v);link(u, v), link(v, u);}dfs(1, 0);ans = (f[1][3][0][0] + f[1][3][0][1]) % Mo;dfs2(1, 0);printf("%d\n", ans);
}

SORTROW

打了一个只交换同行的暴力,骗了1分…

#include <cstring>
#include <cstdio>
#include <algorithm>using namespace std;
typedef long long LL;const int MAXN = 305;struct Node {int num, s;Node(int a, int b) {num = a, s = b;}Node() {}
};Node b[MAXN];
int n, a[MAXN][MAXN];
typedef long long LL;bool cmp(Node a, Node b) {return a.num < b.num;
}void solve() {for (int i = 1; i <= n; i ++) {for (int j = 1; j <= n; j ++) b[j] = Node(a[i][j], j);sort(b + 1, b + n + 1, cmp);LL ans1 = 0, ans2 = 0;for (int j = 1; j <= n; j ++)ans1 = 1ll * (b[j].s - j) * (b[j].s - j);reverse(b + 1, b + n + 1);for (int j = 1; j <= n; j ++) ans2 = 1ll * (b[j].s - j) * (b[j].s - j);if (ans1 < ans2) reverse(b + 1, b + n + 1);for (int j = 1; j <= n; j ++) printf("%d ", b[j].num);printf("\n");}
}int main() {scanf("%d", &n);for (int i = 1; i <= n; i ++)for (int j = 1; j <= n; j ++)scanf("%d", &a[i][j]);solve();
}

CodeChef March Challenge 2017 题解相关推荐

  1. CFCC百套计划2 CodeChef December Challenge 2017 Chef And Easy Xor Queries

    https://www.codechef.com/DEC17/problems/CHEFEXQ 题意: 位置i的数改为k 询问区间[1,i]内有多少个前缀的异或和为k 分块 sum[i][j] 表示第 ...

  2. CodeChef June Challenge 2017

    好气啊,本来以为比赛时间还有很多,结果回家养病两天回到学校怎么比赛就结束了(雾),大约是小高考弄错了时间? 挑3道有意思的写写题解吧. Cloning 题目大意:给一个序列,每次询问两个等长区间,问区 ...

  3. codechef October Challenge 2017解题报告

    第二次打challenge..果然还是拿不到钱(艹不过大佬)啊. A Balanced Contest 模拟就好. #include <bits/stdc++.h> #define gc ...

  4. codechef November Challenge 2017解题报告

    第二次被ceilks艹翻的无奈啊.. Villages and Tribes 模拟不解释 #include <bits/stdc++.h> #define gc getchar() #de ...

  5. 亚马逊采摘挑战赛APC:6D姿态估计的多视图自我监督深度学习6D Pose Estimation in the Amazon Picking Challenge—2017(笔记)

    Multi-view Self-supervised Deep Learning for 6D Pose Estimation in the Amazon Picking Challenge-2017 ...

  6. 【视觉目标跟踪最高峰】VOT Challenge 2017 亚军北邮团队技术分享(附代码)

    视觉跟踪领域国际顶级赛事 Visual-Object-Tracking Challenge (VOT) 2017年结果出炉,结合传统滤波及深度学习的方案取得最佳成绩.本文是第二名北京邮电大学代表团队的 ...

  7. [题解]CodeChef APRIL Challenge 17

    Similar Dishes 题意简述 给你两个大小为 4 4的字符串集合,问你并集是不是空集. 数据范围 1≤T≤2001 \leq T \leq 200 2≤len≤10 2 \leq len \ ...

  8. Codechef June Challenge 2020 简要题解

    这次题目比较简单. The Tom and Jerry Game! 略 Operations on a Tuple 略 The Delicious Cake 略 Convenient Airports ...

  9. CodeChef March Lunchtime 2018 div2

    地址https://www.codechef.com/LTIME58B?order=desc&sortBy=successful_submissions 简单做了一下,前三题比较水,第四题应该 ...

最新文章

  1. SortedList 泛型类
  2. cas协议,以及tomcat搭建cas服务器
  3. 2021 - 10 -7 ! 二叉树的前序、中序、后序遍历 非递归思路(迭代版本)
  4. 【Linux系统编程】进程间通信--共享内存
  5. python打开setting_Django自带日志 settings.py文件配置方法
  6. Python-100例(7-8) 复制列表 打印乘法口诀
  7. java smtp pop3_POP3/SMTP指令
  8. 如何对PDF文件的文字图片编辑修改
  9. 无法打开包括文件的解决办法
  10. vue+element-ui select必填项验证回显问题+实现重置表单内容
  11. Google 2018 IO 大会要点
  12. Django 创建随机验证码
  13. 成绩不好的穷孩子,该做出选择了
  14. ArcGIS学习笔记-1.功能-1.4 矢量图基本
  15. EasyExcel 批量添加批注
  16. 家用计算机网络的传输介质,计算机网络传输介质
  17. 3650m5设置u盘启动_联想启天M415设置u盘启动步骤(支持uefi/bios双启动)
  18. 将N阶矩阵M置成单位阵
  19. 大学计算机实践论文,大学计算机实践论文.docx
  20. 在matlab中使用spm8,spm8处理流程.doc

热门文章

  1. 浪潮之巅第五章——奔腾的芯(Intel)
  2. 为什么IDEA比Eclipse更好
  3. 【英语四六级】成绩查询时间定了!
  4. 音乐网站 Ccmusic-client前台 说明文档
  5. linux随笔记 - SPI驱动
  6. 说说我的专业计算机作文,我家的电脑作文
  7. Java对接Zebra斑马打印机打印条形码相关
  8. 数据图像处理——期末复习题库
  9. 潜意识的力量 (八)
  10. 在 Word 中添加页码