[题解]NOIP2017 Day2 Solution
来源:互联网 发布:haskell linux 编辑:程序博客网 时间:2024/05/22 09:39
感觉Day2比2013还恶心……后来看了清华爷zzq的讲解,才搞出T2。
T1 cheese
模拟题。把可以互相到达的球连边后,用bfs或并查集判断是否连通。
注意细(keng)节(dian):在极端情况下,两点之间的距离会达到
代码:
#include <cmath>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;inline int read() { int res = 0; bool bo = 0; char c; while (((c = getchar()) < '0' || c > '9') && c != '-'); if (c == '-') bo = 1; else res = c - 48; while ((c = getchar()) >= '0' && c <= '9') res = (res << 3) + (res << 1) + (c - 48); return bo ? ~res + 1 : res;}const int N = 1005; const double eps = 1e-8;int n, h, r, X[N], Y[N], Z[N], fa[N]; double DIS;inline int cx(const int &x) { if (fa[x] != x) fa[x] = cx(fa[x]); return fa[x];}inline void zm(const int &x, const int &y) { int ix = cx(x), iy = cx(y); if (ix != iy) fa[iy] = ix;}inline bool check(const int &i, const int &j) { if (X[i] - X[j] > (r << 1) || Y[i] - Y[j] > (r << 1) || Z[i] - Z[j] > (r << 1)) return 0; double dis = 1.0 * (X[i] - X[j]) * (X[i] - X[j]) + 1.0 * (Y[i] - Y[j]) * (Y[i] - Y[j]) + 1.0 * (Z[i] - Z[j]) * (Z[i] - Z[j]); return abs(DIS - dis) <= eps || dis < DIS;}void work() { int i, j; n = read(); h = read(); r = read(); DIS = 4.0 * r * r; for (i = 1; i <= n + 2; i++) fa[i] = i; for (i = 1; i <= n; i++) X[i] = read(), Y[i] = read(), Z[i] = read(); for (i = 1; i < n; i++) for (j = i + 1; j <= n; j++) if (check(i, j)) zm(i, j); for (i = 1; i <= n; i++) { if (Z[i] <= r) zm(n + 1, i); if (Z[i] >= h - r) zm(i, n + 2); } puts(cx(n + 1) == cx(n + 2) ? "Yes" : "No");}int main() { //freopen("cheese.in", "r", stdin); //freopen("cheese.out", "w", stdout); int T = read(); while (T--) work(); return 0;}
T2 treasure
看到
容易推出转移:
其中
for (i = (S - 1) & S; i; i = (i - 1) & S);
这时候复杂度为
这时候,转移方程优化为:
复杂度
代码:
#include <cmath>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;inline int read() { int res = 0; bool bo = 0; char c; while (((c = getchar()) < '0' || c > '9') && c != '-'); if (c == '-') bo = 1; else res = c - 48; while ((c = getchar()) >= '0' && c <= '9') res = (res << 3) + (res << 1) + (c - 48); return bo ? ~res + 1 : res;}const int N = 16, C = (1 << 12) + 5, INF = 0x3f3f3f3f;int n, m, G[N][N], f[N][N][C], g[N][N][C];void dfs(int u, int dep, int S) { if (f[u][dep][S] != -1) return; if (S == (1 << u - 1)) return (void) (f[u][dep][S] = g[u][dep][S] = 0); int i, j; f[u][dep][S] = g[u][dep][S] = INF; for (j = (S - 1) & S; j; j = (j - 1) & S) { if ((j >> u - 1) & 1) continue; dfs(u, dep, S - j); dfs(u, dep + 1, j); f[u][dep][S] = min(f[u][dep][S], f[u][dep][S - j] + g[u][dep + 1][j]); } for (i = 1; i <= n; i++) { if (!((S >> i - 1) & 1) || G[u][i] == INF) continue; dfs(i, dep, S); g[u][dep][S] = min(g[u][dep][S], f[i][dep][S] + G[u][i] * (dep - 1)); }}int main() { //freopen("treasure.in", "r", stdin); //freopen("treasure.out", "w", stdout); memset(G, INF, sizeof(G)); memset(f, -1, sizeof(f)); int i, j, k, x, y, z, ans = INF; n = read(); m = read(); for (i = 1; i <= m; i++) { x = read(); y = read(); z = read(); G[x][y] = min(G[x][y], z); G[y][x] = min(G[y][x], z); } for (i = 1; i <= n; i++) ans = min(ans, (dfs(i, 1, (1 << n) - 1), f[i][1][(1 << n) - 1])); cout << ans << endl; return 0;}
T3 phalanx
好像是NOIP有史以来第一道数据结构题。
蒟蒻用的是Splay的做法,即用
考虑到空间问题,对于前据说标算是树状数组。
代码:
#include <cmath>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;inline int read() { int res = 0; bool bo = 0; char c; while (((c = getchar()) < '0' || c > '9') && c != '-'); if (c == '-') bo = 1; else res = c - 48; while ((c = getchar()) >= '0' && c <= '9') res = (res << 3) + (res << 1) + (c - 48); return bo ? ~res + 1 : res;}typedef long long ll;const int N = 3e6 + 5;int n, m, q, T, fa[N], lc[N], rc[N], rt[N]; ll sze[N], L[N], R[N];int which(int x) {return rc[fa[x]] == x;}void upt(int x) { sze[x] = R[x] - L[x] + 1; if (lc[x]) sze[x] += sze[lc[x]]; if (rc[x]) sze[x] += sze[rc[x]];}void rotate(int x) { int y = fa[x], z = fa[y], b = lc[y] == x ? rc[x] : lc[x]; if (z) (lc[z] == y ? lc[z] : rc[z]) = x; fa[x] = z; fa[y] = x; if (b) fa[b] = y; if (lc[y] == x) rc[x] = y, lc[y] = b; else lc[x] = y, rc[y] = b; upt(y); upt(x);}void splay(int x, int tar, int r) { while (fa[x] != tar) { if (fa[fa[x]] != tar) { if (which(x) == which(fa[x])) rotate(fa[x]); else rotate(x); } rotate(x); } if (!tar) rt[r] = x;}void BuildRow(int row) { int i, x = ++T; L[rt[row] = x] = 1ll * (row - 1) * m + 1; R[x] = 1ll * row * m - 1; fa[lc[x] = ++T] = x; fa[rc[x] = ++T] = x; sze[lc[x]] = sze[rc[x]] = 1; L[lc[x]] = R[lc[x]] = 1ll * (row - 1) * m; L[rc[x]] = R[rc[x]] = 1ll * row * m; upt(x);}int BuildLast(int l, int r) { int mid = l + r >> 1, x = ++T; if (l == 0 && r == n + 1) rt[n + 1] = x; if (l < mid) fa[lc[x] = BuildLast(l, mid - 1)] = x; if (mid < r) fa[rc[x] = BuildLast(mid + 1, r)] = x; L[x] = R[x] = 1ll * mid * m; return upt(x), x;}void build() { int i; for (i = 1; i <= n; i++) BuildRow(i); BuildLast(0, n + 1);}void DivLeft(int x, ll mid) { int y = lc[x], z = ++T; fa[lc[x] = z] = x; if (y) fa[lc[z] = y] = z; L[z] = L[x]; L[x] = mid + 1; R[z] = mid; upt(z); upt(x);}void DivRight(int x, ll mid) { int y = rc[x], z = ++T; fa[rc[x] = z] = x; if (y) fa[rc[z] = y] = z; R[z] = R[x]; R[x] = mid - 1; L[z] = mid; upt(z); upt(x);}void Divide(int x, ll mid) { ll tl = L[x], tr = R[x]; if (tl < mid) DivLeft(x, mid - 1); if (mid < tr) DivRight(x, mid + 1);}void Find(int wh, ll rk, int tar) { int x = rt[wh]; while (x) { ll tmp = lc[x] ? sze[lc[x]] : 0; if (rk > tmp && rk <= tmp + (R[x] - L[x] + 1)) return splay(x, tar, wh), Divide(x, L[x] + rk - tmp - 1); else if (rk <= tmp) x = lc[x]; else rk -= tmp + (R[x] - L[x] + 1), x = rc[x]; }}ll query(int x, int y) { ll res; Find(x, y, 0); Find(x, y + 2, rt[x]); int u = rt[x], v = rc[u], w = lc[v]; res = L[w]; fa[w] = lc[v] = 0; upt(v); upt(u); Find(n + 1, x, 0); Find(n + 1, x + 2, rt[n + 1]); int r = rt[n + 1], s = rc[r], t = lc[s]; fa[t] = lc[s] = 0; upt(s); upt(r); Find(x, m - 1, 0); Find(x, m, rt[x]); fa[lc[rc[rt[x]]] = t] = rc[rt[x]]; upt(rc[rt[x]]); upt(rt[x]); Find(n + 1, n, 0); Find(n + 1, n + 1, rt[n + 1]); fa[lc[rc[rt[n + 1]]] = w] = rc[rt[n + 1]]; return upt(rc[rt[n + 1]]), upt(rt[n + 1]), res;}ll ask(int x) { ll res; Find(n + 1, x, 0); Find(n + 1, x + 2, rt[n + 1]); int u = rt[n + 1], v = rc[u], w = lc[v]; res = L[w]; fa[w] = lc[v] = 0; upt(v); upt(u); Find(n + 1, n, 0); Find(n + 1, n + 1, rt[n + 1]); fa[lc[rc[rt[n + 1]]] = w] = rc[rt[n + 1]]; return upt(rc[rt[n + 1]]), upt(rt[n + 1]), res;}int main() { //freopen("phalanx.in", "r", stdin); //freopen("phalanx.out", "w", stdout); int x, y; n = read(); m = read(); q = read(); build(); while (q--) { x = read(); y = read(); printf("%lld\n", y == m ? ask(x) : query(x, y)); } return 0;}
- [题解]NOIP2017 Day2 Solution
- [题解]NOIP2017 Day1 Solution
- NOIP2017 day2 t2 treasure题解
- 【NOIP2017】Day2
- 【NOIP2017】Day2代码
- NOIP2017 游记 Day2
- NOIP2017题解
- NOIP2017题解
- noip2017题解
- NOIP2017 模拟考试 day2 2017.10.07
- noip2011题解day2
- AOI2009 DAY2 题解
- 11-Day2 题解
- noip2011(day2)题解
- JZWC【Day2】题解&总结
- JSOI2015 Round2 Day2题解
- 【NOIP2013 day2】华容道 题解
- 集训题解-Day2
- sublime3保存谷歌同步刷新插件安装
- W: 无法下载 http://ppa.launchpad.net/fcitx-team/nightly/ubuntu/dists/jessie/main/binary-amd64/Packages
- 关于ListView中adapter调用notifyDataSetChanged失效的原因总结
- 使用table表格设计调查表
- 手机号验证,为jquery-validation添加自定义验证方式,以及Ajax提交form表单
- [题解]NOIP2017 Day2 Solution
- [C/C++]C语言中math.h和cmath的pow()精度问题
- MySQL通过.frm和.ibd恢复表结构和数据
- C#类的封装
- kotlin语法分析(一)
- spring boot实现session 同步共享及 根据sessionid 获取相应的session
- 瞎脑洞毒瘤题
- kotlin语法分析(二)
- 调试符号环境变量正确配置方法