CodeForces 293E Close Vertices 点分治

题目传送门

题意:现在有一棵树,每条边的长度都为1,然后有一个权值,求存在多少个(u,v)点对,他们的路劲长度 <= l, 总权重 <= w.

题解:

1.找到树的重心。

2.求出每个点到中心的长度和权值。

3.对所有点都询问出合法点的个数(包括同一颗子树)加到答案上。

4.对于每一棵子树内部都找到合法点的个数从答案中减去。

5.递归处理每一颗子树。

我们现在最大的问题就是怎么计算合法点的个数。

我们把点的信息记录下来之后,按照权重从小到达排序。

然后我们就可以用2个端点维护出 a[l].weight + a[r].weight <= d

这样对于l来说, [l+1,r]里面的所有点都满足权重的条件了。

然后就只需要询问 [l+1,r]里面的点的深度 <= l - deep[i]的个数了,对于这个个数我们用树状数组去维护这个信息,一开始我们把所有的点的深度都加到树状数组里面,然后每次端点移动位置的时候都把当前点的深度从树状数组中移除,这样我们维护出了一颗[ l+1 , r] 里面的点的深度信息了。

代码:

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
  4 #define LL long long
  5 #define ULL unsigned LL
  6 #define fi first
  7 #define se second
  8 #define pb push_back
  9 #define lson l,m,rt<<1
 10 #define rson m+1,r,rt<<1|1
 11 #define lch(x) tr[x].son[0]
 12 #define rch(x) tr[x].son[1]
 13 #define max3(a,b,c) max(a,max(b,c))
 14 #define min3(a,b,c) min(a,min(b,c))
 15 typedef pair<int,int> pll;
 16 const int inf = 0x3f3f3f3f;
 17 const LL INF = 0x3f3f3f3f3f3f3f3f;
 18 const LL mod =  (int)1e9+7;
 19 const int N = 5e5 + 100;
 20 int n, len, w;
 21 int tree[N];
 22 int root, sz[N], mxr;
 23 int vis[N];
 24 int head[N], to[N*2], nt[N*2], ct[N*2];
 25 void add(int x, int v){
 26     for(int i = x; i <= n && i; i += i & (-i))
 27         tree[i] += v;
 28 }
 29 int query(int x){
 30     int ret = 0;
 31     for(int i = x; i; i -= i&(-i))
 32         ret += tree[i];
 33     return ret;
 34 }
 35 void getW(int o, int u, int num){
 36     sz[u] = 1;
 37     int mx = 0;
 38     for(int i = head[u]; ~i; i = nt[i]){
 39         int v = to[i];
 40         if(vis[v] || v == o) continue;
 41         getW(u, v, num);
 42         sz[u] += sz[v];
 43         mx = max(mx, sz[v]);
 44     }
 45     if(o) mx = max(mx, num-sz[u]);
 46     if(mx < mxr) mxr = mx, root = u;
 47 }
 48 //pll p[N];
 49 struct Node {
 50     int fi, se;
 51     bool operator < (const Node & x) const {
 52         if(fi == x.fi) return se < x.se;
 53         return fi < x.fi;
 54     }
 55 }p[N];
 56 LL cal(int l, int r){
 57     if(l >= r) return 0;
 58     sort(p+l, p+r+1);
 59     LL ans = 0;
 60     for(int i = l; i <= r; i++) add(p[i].se, 1);
 61     for(int L = l, R = r; L <= R; L++){
 62         while(L < R && p[L].fi + p[R].fi > w) {
 63             add(p[R].se, -1);
 64             R--;
 65         }
 66         add(p[L].se, -1);
 67         if(L >= R) break;
 68         ans += query(max(0, len-p[L].se));
 69     }
 70     return ans;
 71 }
 72 
 73 int sum = 0;
 74 void Dfs(int o, int u, int deep, int w){
 75     sz[u] = 1;
 76     ++sum;
 77     p[sum].fi = w;
 78     p[sum].se = deep;
 79     for(int i = head[u]; ~i; i = nt[i]){
 80         int v = to[i];
 81         if(v == o || vis[v]) continue;
 82         Dfs(u, v, deep+1, w+ct[i]);
 83         sz[u] += sz[v];
 84     }
 85 }
 86 LL ans = 0;
 87 void GG(int id, int num){
 88     if(num == 1){
 89         return ;
 90     }
 91     mxr = inf;
 92     getW(0, id, num);
 93     vis[root] = 1;
 94     int ls = 1; sum = 0;
 95     for(int i = head[root]; ~i; i = nt[i]){
 96         int v = to[i];
 97         if(vis[v]) continue;
 98         Dfs(0, to[i], 1, ct[i]);
 99         ans -= cal(ls, sum);
100         ls = sum + 1;
101     }
102     sum++;
103     p[sum].fi = p[sum].se = 0;
104     ans += cal(1, sum);
105     //cout << query(n) << endl;
106     for(int i = head[root]; ~i; i = nt[i]){
107         int v = to[i];
108         if(vis[v]) continue;
109         GG(v, sz[v]);
110     }
111 }
112 int tot = 0;
113 void add(int u, int v, int w){
114     to[tot] = v;
115     ct[tot] = w;
116     nt[tot] = head[u];
117     head[u] = tot++;
118 }
119 int main(){
120     memset(head, -1, sizeof(head));
121     scanf("%d%d%d", &n, &len, &w);
122     int u, v, val;
123     for(int i = 2; i <= n; i++){
124         u = i;
125         scanf("%d%d", &v, &val);
126         add(u, v, val);
127         add(v, u, val);
128     }
129     GG(1, n);
130     printf("%I64d\n", ans);
131     return 0;
132 }
133   
View Code

猜你喜欢

转载自www.cnblogs.com/MingSD/p/9761981.html