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;
}

  

posted @ 2018-09-12 23:52  AnzheWang  阅读(298)  评论(0编辑  收藏  举报