zoukankan      html  css  js  c++  java
  • 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
    ", ans);
    131     return 0;
    132 }
    133   
    View Code
  • 相关阅读:
    DataGrip for Mac破解步骤详解 亲测好用
    git 之路
    linux用户管理
    virtualenvwrappers pipreqs 踩坑
    pycharm 快捷键
    kubernetes(k8s)之K8s部署多种服务yaml文件
    centos下彻底删除mysql的方法
    vi 和vim 的区别
    Django中related_name作用
    Windows CMD命令大全
  • 原文地址:https://www.cnblogs.com/MingSD/p/9761981.html
Copyright © 2011-2022 走看看