zoukankan      html  css  js  c++  java
  • hdu_4918_Query on the subtree(树的分治+树状数组)

    题目链接:hdu_4918_Query on the subtree

    题意:

    给出一颗n个点的树,每个点有一个权值,有两种操作,一种是将某个点的权值修改为v,另一种是查询距离点u不超过d的点的权值和。

    题解:

    这里可以去膜膜鸟神的博客

    简单来说就是对树的每个重心建立两个树状数组,然后对于每个点修改就在每个重心的BIT中去修改,查询也在每个重心的BIT中查询,然后容斥一下,就得出答案。

    每种操作的复杂度为log2n,这题的细节比较多,具体看代码。

      1 #include<bits/stdc++.h>
      2 #define F(i,a,b) for(int i=a;i<=b;i++)
      3 #define pb push_back
      4 using namespace std;
      5 const int N=1e5+7;
      6 
      7 int n,q,g[N],nxt[N*2],v[N*2],ed,w[N],vis[N],id[N];
      8 int pool[40*N],C_ed,pool_ed,sz[N],mi,mx[N],ROOT;
      9 char op[2];
     10 
     11 struct node
     12 {
     13     int rt,subrt,dis;
     14     node(){}
     15     node(int _rt,int _subrt,int _dis):rt(_rt),subrt(_subrt),dis(_dis){}
     16 }tmp;
     17 vector<node>vt[N];
     18 
     19 void adg(int x,int y){v[++ed]=y,nxt[ed]=g[x],g[x]=ed;}
     20 void init(){ed=C_ed=pool_ed=0;F(i,1,n)vt[i].clear(),vis[i]=g[i]=0;}
     21 inline void up(int &a,int b){if(a<b)a=b;}
     22 
     23 struct BIT
     24 {
     25     int *C,n;
     26     void init(int tot){n=tot,C=pool+pool_ed,pool_ed+=tot+1;F(i,0,n)C[i]=0;}
     27     inline void add(int x,int c){while(x<=n)C[x]+=c,x+=x&-x;}
     28     inline int ask(int x,int an=0)
     29     {
     30         if(x>n)x=n;
     31         while(x>0)an+=C[x],x-=x&-x;
     32         return an;
     33     }
     34 }tr[N*2];
     35 
     36 void get_rt(int u,int fa,int num)
     37 {
     38     sz[u]=1,mx[u]=0;
     39     for(int i=g[u];i;i=nxt[i])
     40         if(!vis[v[i]]&&v[i]!=fa)
     41         {
     42             get_rt(v[i],u,num);
     43             sz[u]+=sz[v[i]],up(mx[u],sz[v[i]]);
     44         }
     45     up(mx[u],num-sz[u]);
     46     if(mx[u]<mi)ROOT=u,mi=mx[u];
     47 }
     48 
     49 void del(int u,int fa,int rt,int subrt,int dis=1)//将子树的每个点放进对应的重心
     50 {
     51     vt[u].pb(node(rt,subrt,dis));
     52     tr[rt].add(dis+1,w[u]);
     53     tr[subrt].add(dis+1,w[u]);
     54     for(int i=g[u];i;i=nxt[i])
     55         if(v[i]!=fa&&!vis[v[i]])
     56             del(v[i],u,rt,subrt,dis+1);
     57 }
     58 
     59 void init_tree(int u=1,int num=n)
     60 {
     61     mi=N,get_rt(u,u,num);
     62     int rt=ROOT,rt_id=++C_ed;
     63     tr[C_ed].init(sz[u]+2);
     64     vis[rt]=1,vt[rt].pb(node(C_ed,0,0));
     65     tr[C_ed].add(1,w[rt]);
     66     get_rt(rt,rt,num);//从新计算sz的大小
     67     for(int i=g[rt];i;i=nxt[i])
     68         if(!vis[v[i]])
     69         {
     70             tr[++C_ed].init(sz[v[i]]+2);
     71             del(v[i],v[i],rt_id,C_ed);
     72         }
     73     for(int i=g[rt];i;i=nxt[i])
     74         if(!vis[v[i]])
     75             init_tree(v[i],sz[v[i]]);
     76 }
     77 
     78 int main()
     79 {
     80     while(~scanf("%d%d",&n,&q))
     81     {
     82         init();
     83         F(i,1,n)scanf("%d",w+i);
     84         F(i,1,n-1)
     85         {
     86             int x,y;
     87             scanf("%d%d",&x,&y);
     88             adg(x,y),adg(y,x);
     89         }
     90         init_tree();
     91         while(q--)
     92         {
     93             int u,v;
     94             scanf("%s%d%d",op,&u,&v);
     95             if(op[0]=='!')
     96             {
     97                 int size=vt[u].size(),d=v-w[u];
     98                 F(i,0,size-1)
     99                 {
    100                     tmp=vt[u][i];
    101                     tr[tmp.rt].add(tmp.dis+1,d);//dis+1去掉距离为0在BIT上超时的BUG
    102                     if(tmp.subrt)tr[tmp.subrt].add(tmp.dis+1,d);
    103                 }
    104                 w[u]+=d;
    105             }else
    106             {
    107                 int d=v,ans=0,size=vt[u].size();
    108                 F(i,0,size-1)
    109                 {
    110                     tmp=vt[u][i];
    111                     ans+=tr[tmp.rt].ask(d-tmp.dis+1);
    112                     if(tmp.subrt)ans-=tr[tmp.subrt].ask(d-tmp.dis+1);
    113                 }
    114                 printf("%d
    ",ans);
    115             }
    116         }
    117     }
    118     return 0;
    119 }
    View Code
  • 相关阅读:
    试述软件的概念和特点?软件复用的含义?构件包括哪些?
    Spring Security基本用法
    java中跳出循环的方式
    cookie和session区别
    spring中类型注解下的bean的加载顺序
    常见的异常
    aop使用场景
    缓存类似于redis
    旧版redis使用
    获取rdis的几种方式
  • 原文地址:https://www.cnblogs.com/bin-gege/p/6125407.html
Copyright © 2011-2022 走看看