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;
    }
    
  • 相关阅读:
    mybatis
    mybatis
    hadoop完全分布式搭建
    用构造器确保初始化
    HashMap的内部结构与hash冲突
    方法重载 与 方法覆盖
    Django后台管理admin或者adminx中使用富文本编辑器
    Celery在Django中的使用介绍
    django.db.utils.InternalError: (1060, "Duplicate column name 'user_id'")迁移报错解决方法
    Django2.0版本以上与pymsql 不匹配问题以及解决方法
  • 原文地址:https://www.cnblogs.com/tuchen/p/15308775.html
Copyright © 2011-2022 走看看