zoukankan      html  css  js  c++  java
  • [USACO18JAN]Lifeguards P(构造+点分治)

    [USACO18JAN]Lifeguards P(构造+点分治)

    题目大意

    贝茜被农民们逼进了一个偏僻的农场。农场可视为一棵有 (N) 个结点的树,结点分别编号为 (1,2,ldots, N) 。每个叶子结点都是出入口。开始时,每个出入口都可以放一个农民(也可以不放)。每个时刻,贝茜和农民都可以移动到相邻的一个结点。如果某一时刻农民与贝茜相遇了(在边上或点上均算),则贝茜将被抓住。抓捕过程中,农民们与贝茜均知道对方在哪个结点。

    请问:对于结点 (i\,(1le ile N)) ,如果开始时贝茜在该结点,最少有多少农民,她才会被抓住。

    数据范围

    (2 leq N leq 7 cdot 10^4)

    解题思路

    神题++ 贝西贝西贝西呦

    (deg[x],~d[x],~dep[x]) 分别指 x 的度数,x 距离叶子节点的最短距离,以 rt 为根时,x 的深度

    容易发现贝西在点 x 被截住的条件是 (d[x] <= dep[x]) 且 贝西没在 x 父亲处被截住,那么 x 对答案的贡献为 1。暴力 dfs 是 (Theta(n^2))

    构造,发现 x 满足截住条件的话它的子树都会满足条件,让整个子树都产生贡献并且贡献之和为 1,即 ((sum_{iin subtree(x)}val[i]) = 1),又因为 ((sum_{i in subtree(x)}deg[i]) = 2 cdot m-1),那么 (val[x] = 2 - deg[x]) 即可

    于是可以点分治 (ans[x] = sum_{i = 1}^n [dist(x, i) >= d[i]] * (2-deg[i])),利用单调性点分治 + 排序即可

    时间复杂度 (T(N) = 2 * T(frac N2) + NlogN = Nlog^2N)

    #include <queue>
    #include <vector>
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define MP make_pair
    #define ll long long
    #define fi first
    #define se second
    using namespace std;
    
    template <typename T>
    void read(T &x) {
        x = 0; bool f = 0;
        char c = getchar();
        for (;!isdigit(c);c=getchar()) if (c=='-') f=1;
        for (;isdigit(c);c=getchar()) x=x*10+(c^48);
        if (f) x=-x;
    }
    
    template<typename F>
    inline void write(F x)
    {
    	static short st[30];short tp=0;
    	if(x<0) putchar('-'),x=-x;
    	do st[++tp]=x%10,x/=10; while(x);
    	while(tp) putchar('0'|st[tp--]);
    	putchar('
    ');
    }
    
    template <typename T>
    inline void Mx(T &x, T y) { x < y && (x = y); }
    
    template <typename T>
    inline void Mn(T &x, T y) { x > y && (x = y); }
    
    const int N = 200500;
    int deg[N], d[N], h[N], ne[N], to[N], tot;
    inline void add(int x, int y) {
    	ne[++tot] = h[x], deg[to[h[x] = tot] = y]++;
    }
    
    
    void Dfs(int x, int fa) {
    	if (deg[x] == 1) d[x] = 0;
    	for (int i = h[x]; i; i = ne[i]) {
    		int y = to[i]; if (y == fa) continue;
    		Dfs(y, x); Mn(d[x], d[y] + 1);
    	}
    }
    
    void Dfs(int x, int fa, int mn) {
    	Mn(mn, d[x]), Mn(d[x], mn);
    	for (int i = h[x]; i; i = ne[i]) 
    		if (to[i] != fa) Dfs(to[i], x, mn + 1);
    }
    
    int ans[N], vis[N], siz[N], sz, mn, rt, n;
    
    void get_rt(int x, int fa) {
    	siz[x] = 1; int mx = 0;
    	for (int i = h[x]; i; i = ne[i]) {
    		int y = to[i]; if (vis[y] || y == fa) continue;
    		get_rt(y, x); siz[x] += siz[y]; Mx(mx, siz[y]);
    	}
    	Mx(mx, sz - siz[x]);
    	if (mx < mn) mn = mx, rt = x;
    }
    
    
    
    int sam[N], bl[N], sum, tmp, t1, t2;
    pair<int, int> A[N], B[N];
    void get(int x, int fa, int dep) {
    	bl[x] = tmp;
    	A[++t1] = MP(dep, x), B[++t2] = MP(d[x] - dep, x);
    	for (int i = h[x]; i; i = ne[i]) {
    		int y = to[i]; 
    		if (vis[y] || y == fa) continue;
    		get(y, x, dep + 1);
    	}
    }
    
    void solve(int x) {
    	vis[bl[x] = x] = 1, sam[x] = 0, t1 = t2 = 0;
    	A[++t1] = MP(0, x), B[++t2] = MP(d[x], x);
    	for (int i = h[x]; i; i = ne[i])
    		if (!vis[tmp = to[i]]) sam[tmp] = 0, get(tmp, x, 1);
    	sort(A + 1, A + t1 + 1), sort(B + 1, B + t2 + 1);
    	
    	ll sum = 0, j = 0;
    	for (int i = 1;i <= t1; i++) {
    		while (j < t1 && B[j+1].fi - A[i].fi <= 0) 
    			++j, sum += 2 - deg[B[j].se], sam[bl[B[j].se]] += 2 - deg[B[j].se];
    		ans[A[i].se] += sum - sam[bl[A[i].se]];
    	}
    	
    	for (int i = h[x]; i; i = ne[i]) {
    		int y = to[i]; if (vis[y]) continue;
    		sz = siz[rt = y], mn = n, get_rt(y, 0);
    		solve(rt);
    	}
    }
    
    int main() {
    	read(n);
    	for (int i = 1, x, y; i < n ; i++)
    		read(x), read(y), add(x, y), add(y, x);
    	memset(d, 0x3f, sizeof(d));
    	Dfs(1, 0), Dfs(1, 0, 1e8);
    	rt = 1, sz = mn = n; get_rt(1, 0), solve(rt);
    	for (int i = 1;i <= n; i++)
    		write(deg[i] == 1 ? 1 : ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    MySQL性能调优——索引详解与索引的优化
    Linux命令之文件搜索
    MySQL中的行级锁,表级锁,页级锁
    MySQL存储引擎
    Linux软链接和硬链接
    linux学习笔记
    在浏览器中输入一个网址后,发生了什么?
    二叉排序树
    有序表查找
    为view设置虚线边框
  • 原文地址:https://www.cnblogs.com/Hs-black/p/12830682.html
Copyright © 2011-2022 走看看