NOIP2017 Day2 题解
A - 奶酪
直接用并查集维护即可。(本来一个dfs就够了)
#include <cstdio> #include <cstring> #include <cstdlib> #include <algorithm> #include <ctime> #include <iostream> #include <queue> #include <stack> #define rep(i, a, b) for(rint (i) = (a), __omega = (b); (i) <= __omega; ++(i)) #define rint rg int #define rg register namespace work { int F() { rg char ch; rint x, a; while(ch = getchar(), (ch < '0' || ch > '9') && ch != '-'); if(ch == '-') a = -1, ch = getchar(); else a = 1; x = ch-'0'; while(ch = getchar(), ch >= '0' && ch <= '9') x = (x<<1)+(x<<3)+ch-'0'; return x*a; } struct point { int x, y, z; point(int X = 0, int Y = 0, int Z = 0) : x(X), y(Y), z(Z) { } long long dis2() { return 1ll*x*x+1ll*y*y+1ll*z*z; } point operator-(rg const point &that) { return point(x-that.x, y-that.y, z-that.z); } } p[1010]; int fa[1010], siz[1010]; int find(rint x) { return x == fa[x] ? x : fa[x] = find(fa[x]); } void unit(rint x, rint y) { x = find(x), y = find(y); if(siz[x] < siz[y]) std::swap(x, y); siz[x] += siz[y]; fa[y] = x; } void solve() { rint n, h; n = F(), h = F(); rg long long r; r = F(); rep(i, 1, n) fa[i] = i, siz[i] = 1, p[i].x = F(), p[i].y = F(), p[i].z = F(); fa[n+1] = n+1, fa[n+2] = n+2; siz[n+1] = siz[n+2] = 1; rep(i, 1, n) if(p[i].z <= r && p[i].z >= -r) unit(n+1, i); rep(i, 1, n) if(p[i].z >= h-r && p[i].z <= h+r) unit(n+2, i); r = r*r<<2; rep(i, 1, n) rep(j, i+1, n) if((p[j]-p[i]).dis2() <= r) unit(i, j); if(find(n+1) == find(n+2)) puts("Yes"); else puts("No"); } void main() { rint test = F(); while(test--) solve(); } } int main() { //freopen("cheese.in", "r", stdin); //freopen("cheese.out", "w", stdout); work::main(); return 0; }
B - 宝藏
f[i][k][S]表示第i个点深度为k,集合为S的最小值,枚举子集转移即可。
//waz #include <bits/stdc++.h> using namespace std; #define mp make_pair #define pb push_back #define fi first #define se second #define ALL(x) (x).begin(), (x).end() #define SZ(x) ((int)((x).size())) typedef pair<int, int> PII; typedef vector<int> VI; typedef long long int64; typedef unsigned int uint; typedef unsigned long long uint64; #define gi(x) ((x) = F()) #define gii(x, y) (gi(x), gi(y)) #define giii(x, y, z) (gii(x, y), gi(z)) int F() { char ch; int x, a; while (ch = getchar(), (ch < '0' || ch > '9') && ch != '-'); if (ch == '-') ch = getchar(), a = -1; else a = 1; x = ch - '0'; while (ch = getchar(), ch >= '0' && ch <= '9') x = (x << 1) + (x << 3) + ch - '0'; return a * x; } int n, m; int f[14][14][1 << 12]; int t[14][14]; int main() { gii(n, m); memset(t, -1, sizeof t); for (register int i = 1; i <= m; ++i) { register int a, b, c; giii(a, b, c); if (t[a][b] == -1) t[a][b] = t[b][a] = c; else t[a][b] = t[b][a] = min(t[a][b], c); } memset(f, 63, sizeof f); register int inf = f[0][0][0]; for (register int k = n - 1; ~k; --k) { for (register int i = 1; i <= n; ++i) f[k][i][(1 << (i - 1))] = 0; for (register int s = 1; s < (1 << n); ++s) { for (register int i = 1; i <= n; ++i) { if (!(s & (1 << (i - 1)))) continue; for (register int ss = s - 1; ss; ss = (ss - 1) & s) { if (f[k][i][s ^ ss] == inf) continue; for (register int j = 1; j <= n; ++j) { if (!(ss & (1 << (j - 1)))) continue; if (t[i][j] == -1) continue; f[k][i][s] = min(f[k][i][s], f[k + 1][j][ss] + f[k][i][s ^ ss] + (k + 1) * t[i][j]); } } } } } int ans = 1e9; for (register int i = 1; i <= n; ++i) ans = min(ans, f[0][i][(1 << n) - 1]); printf("%d\n", ans); return 0; }
C - 列队
用动态开点线段树维护哪些要被删除,再用平衡树维护新添加的即可。
//waz #include <bits/stdc++.h> using namespace std; #define mp make_pair #define pb push_back #define fi first #define se second #define ALL(x) (x).begin(), (x).end() #define SZ(x) ((int)((x).size())) typedef pair<int, int> PII; typedef vector<int> VI; typedef long long int64; typedef unsigned int uint; typedef unsigned long long uint64; #define gi(x) ((x) = F()) #define gii(x, y) (gi(x), gi(y)) #define giii(x, y, z) (gii(x, y), gi(z)) int F() { char ch; int x, a; while (ch = getchar(), (ch < '0' || ch > '9') && ch != '-'); if (ch == '-') ch = getchar(), a = -1; else a = 1; x = ch - '0'; while (ch = getchar(), ch >= '0' && ch <= '9') x = (x << 1) + (x << 3) + ch - '0'; return a * x; } const int N = 3e5 + 10; struct node1 { int siz; node1 *ls, *rs; } tr1[N * 20], *nt1 = tr1, *rt1[N], *nul1; void ins1(node1 *&o, int l, int r, int x) { if (r < x || x < l) return; if (!o) o = ++nt1; ++(o -> siz); if (l == r) return; int mid = (l + r) >> 1; ins1(o -> ls, l, mid, x); ins1(o -> rs, mid + 1, r, x); } int kth1(node1 *&o, int l, int r, int k) { if (l == r) return l; int ls = 0, rs = 0; if (o) ls = o -> ls ? o -> ls -> siz : 0, rs = o -> rs ? o -> rs -> siz : 0; int mid = (l + r) >> 1; ls = (mid - l + 1) - ls; rs = (r - mid) - rs; if (k <= ls) return kth1(o ? o -> ls : nul1, l, mid, k); else return kth1(o ? o -> rs : nul1, mid + 1, r, k - ls); } struct node2 { int64 val; int rnd; int siz; node2 *son[2]; node2(int64 v = 0) { val = v, rnd = rand(); siz = 1; son[0] = son[1] = 0; } void push_up() { siz = 1; if (son[0]) siz += son[0] -> siz; if (son[1]) siz += son[1] -> siz; } } tr2[N << 2], *rt2[N], *nt2 = tr2; int siz2(node2 *x) { return x ? x -> siz : 0; } node2 *merge(node2 *x, node2 *y) { if (!x) return y; if (!y) return x; if ((x -> rnd) < (y -> rnd)) { x -> son[1] = merge(x -> son[1], y); x -> push_up(); return x; } else { y -> son[0] = merge(x, y -> son[0]); y -> push_up(); return y; } } pair<node2*, node2*> split(node2 *x, int k) { if (!x) return pair<node2*, node2*>(0, 0); pair<node2*, node2*> ret; if (k <= siz2(x -> son[0])) { ret = split(x -> son[0], k); x -> son[0] = ret.se; x -> push_up(); ret.se = x; return ret; } else { ret = split(x -> son[1], k - siz2(x -> son[0]) - 1); x -> son[1] = ret.fi; x -> push_up(); ret.fi = x; return ret; } } void ins2(node2 *&x, int64 v) { node2 *t = ++nt2; *t = node2(v); x = merge(x, t); } int64 del2(node2 *&x, int k) { pair<node2*, node2*> A = split(x, k - 1); pair<node2*, node2*> B = split(A.se, 1); x = merge(A.fi, B.se); return (B.fi) -> val; } int siz[N]; int main() { srand(time(0)); int n, m, q; giii(n, m, q); for (int i = 1; i <= n; ++i) ins2(rt2[0], 1LL * i * m), siz[i] = m - 1; int id = 0; while (q--) { ++id; int x, y; gii(x, y); if (y != m) { if (y <= siz[x]) { int v = kth1(rt1[x], 1, m - 1, y); int64 val = (x - 1LL) * m + v; printf("%lld\n", val); ins1(rt1[x], 1, m - 1, v); int64 cur = del2(rt2[0], x); ins2(rt2[x], cur); ins2(rt2[0], val); --siz[x]; } else { int64 val = del2(rt2[x], y - siz[x]); printf("%lld\n", val); int64 cur = del2(rt2[0], x); ins2(rt2[x], cur); ins2(rt2[0], val); } } else { int64 val = del2(rt2[0], x); ins2(rt2[0], val); printf("%lld\n", val); } } return 0; }