zoukankan      html  css  js  c++  java
  • icpc2019 香港 C. Constructing Ranches (点分治)

    题目链接:https://codeforces.com/gym/102452/problem/C

    (n) 条边能够形成多边形的结论是所有边之和大于最长的边

    于是点分治,维护每个点到根的路径上的点权和和点权最大值,统计满足 (sum[u]+sum[v]-a[rt]>2 imes max{mx[u], mx[v]}),的点对((u,v))的数量,考虑将所有点的 (sum)(mx) 排序,这样从小到大扫描时保证当前点 (u)(mx) 为最大值,然后树状数组统计满足 (sum[v] > 2*mx[u]-sum[u]+a[rt]) 的点 (v) 的数量,容斥即可

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int maxn = 400010;
    const ll INF = 1e18+7;
    
    int T, n, m;
    ll a[maxn], ans;
    
    int h[maxn], cnt = 0;
    struct E{
    	int to, next;
    }e[maxn<<1];
    void add(int u, int v){
    	e[++cnt].to = v;
    	e[cnt].next = h[u];
    	h[u] = cnt;
    } 
    
    int rt, tot;
    int sz[maxn], son[maxn], vis[maxn], maxson;
    
    void getrt(int u, int par){
    	sz[u] = 1; son[u] = 0;
    	for(int i = h[u] ; i != -1 ; i = e[i].next){
    		int v = e[i].to;
    		if(vis[v] || v == par) continue;
    		getrt(v, u);
    		sz[u] += sz[v];
    		son[u] = max(son[u], sz[v]);
    	}
    	son[u] = max(son[u], tot - sz[u]);
    	if(son[u] < maxson){
    		maxson = son[u];
    		rt = u;
    	}
    }
    
    struct Node{
    	int id;
    	ll dis, mx;
    	
    	bool operator < (const Node & x) const{
    		return mx < x.mx;
    	}
    }p[maxn];
    
    int num = 0;
    ll dis[maxn], mx[maxn], b[maxn];
    void getdis(int u, int par){
    	++num;
    	p[num].id = u, p[num].dis = dis[u], p[num].mx = mx[u];
    	b[num] = dis[u];
    	for(int i = h[u] ; i != -1 ; i = e[i].next){
    		int v = e[i].to;
    		if(vis[v] || v == par) continue;
    		dis[v] = dis[u] + a[v];
    		mx[v] = max(mx[u], a[v]);
    		getdis(v, u);
    	}
    }
    
    int q;
    ll c[maxn];
    
    void ad(int x, int val){
    	for(int i = x ; i <= 200000 ; i += i&(-i)){
    		c[i] += val;
    	}
    }
    
    ll sum(int x){
    	ll res = 0;
    	for(int i = x ; i ; i -= i & (-i)){
    		res += c[i];
    	}
    	return res;
    }
    
    void calc(int u){
    	num = 0;
    	dis[u] = a[u], mx[u] = a[u];
    	getdis(u, 0);
    
    	sort(p+1, p+1+num);
    
    	b[num+1] = INF;
    	sort(b+1, b+1+num+1);
    	q = unique(b+1, b+1+num+1)-b-1;
    	for(int i = 1 ; i <= num ; ++i) {
    		p[i].dis = lower_bound(b+1, b+1+q, p[i].dis)-b;
    	}
    	
    	for(int i = 1 ; i <= num ; ++i){
    		int pos = upper_bound(b+1, b+1+q, 2ll*p[i].mx-b[p[i].dis]+a[u])-b;
    		ans += sum(q) - sum(pos-1);
    		ad(p[i].dis, 1);
    	}
    	
    	for(int i = 1 ; i <= num ; ++i){
    		ad(p[i].dis, -1);
    	}
    	
    	for(int i = h[u] ; i != -1 ; i = e[i].next){
    		int v = e[i].to;
    		if(vis[v]) continue;
    
    		num = 0;
    		dis[v] = a[u]+a[v];
    		mx[v] = max(a[u], a[v]);
    		getdis(v, u);
    		
    		sort(p+1, p+1+num);
    		
    		b[num+1] = INF;
    		sort(b+1, b+1+num+1);
    		q = unique(b+1, b+1+num+1)-b-1;
    		
    		for(int j = 1 ; j <= num ; ++j) {
    			p[j].dis = lower_bound(b+1, b+1+q, p[j].dis)-b;
    		}
    		for(int j = 1 ; j <= num ; ++j){
    			int pos = upper_bound(b+1, b+1+q, 2ll*p[j].mx-b[p[j].dis]+a[u])-b;
    			ans -= sum(q) - sum(pos-1);
    			ad(p[j].dis, 1);
    		} 
    		
    		for(int j = 1 ; j <= num ; ++j){
    			ad(p[j].dis, -1);
    		}
    	}
    }
    
    void divi(int u){
    	calc(u);
    	vis[u] = 1;
    	
    	for(int i = h[u] ; i != -1 ; i = e[i].next){
    		int v = e[i].to;
    		if(vis[v]) continue;
    		maxson = 1000000007, tot = sz[v];
    		getrt(v, u);
    		divi(rt);
    	}
    }
    
    void solve(){
    	maxson = 1000000007, tot = n;
    	getrt(1, 0);
    	divi(rt);
    }
    
    ll read(){ ll s = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); } return s * f; }
    
    int main(){
    	T = read();
    	while(T--){
    		ans = 0;
    		memset(h, -1, sizeof(h));
    		n = read();
    		for(int i = 1 ; i <= n ; ++i) vis[i] = 0;
    		for(int i = 1 ; i <= n ; ++i) a[i] = read();
    		int u, v;
    		for(int i = 1 ; i < n ; ++i){
    			u = read(), v = read();
    			add(u, v); add(v, u);
    		}
    		
    		solve();
    		
    		printf("%lld
    ", ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    Java实现 LeetCode 802 找到最终的安全状态 (DFS)
    Java实现 LeetCode 802 找到最终的安全状态 (DFS)
    Java实现 LeetCode 802 找到最终的安全状态 (DFS)
    Java实现 LeetCode 804 唯一摩尔斯密码词 (暴力)
    Java实现 LeetCode 803 打砖块 (DFS)
    Java实现 LeetCode 804 唯一摩尔斯密码词 (暴力)
    Java实现 LeetCode 803 打砖块 (DFS)
    Java实现 LeetCode 804 唯一摩尔斯密码词 (暴力)
    英文标点
    post sharp 与log4net 结合使用,含执行源码 转拷
  • 原文地址:https://www.cnblogs.com/tuchen/p/15308775.html
Copyright © 2011-2022 走看看