• hdu 4918


    一道比较好的树分治的题目.大力推荐~

    Query on the subtree

    Time Limit: 16000/8000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
    Total Submission(s): 479    Accepted Submission(s): 163


    Problem Description
    bobo has a tree, whose vertices are conveniently labeled by 1,2,…,n. At the very begining, the i-th vertex is assigned with weight wi.

    There are q operations. Each operations are of the following 2 types:

    Change the weight of vertex v into x (denoted as "! v x"),
    Ask the total weight of vertices whose distance are no more than d away from vertex v (denoted as "? v d").

    Note that the distance between vertex u and v is the number of edges on the shortest path between them.
     
    Input
    The input consists of several tests. For each tests:

    The first line contains n,q (1≤n,q≤105). The second line contains n integers w1,w2,…,wn (0≤wi≤104). Each of the following (n - 1) lines contain 2 integers ai,bi denoting an edge between vertices ai and bi (1≤ai,bi≤n). Each of the following q lines contain the operations (1≤v≤n,0≤x≤104,0≤d≤n).
     
    Output
    For each tests:

    For each queries, a single number denotes the total weight.
     
    Sample Input
    4 3
    1 1 1 1
    1 2
    2 3
    3 4
    ? 2 1
    ! 1 0
    ? 2 1
    3 3
    1 2 3
    1 2
    1 3
    ? 1 0
    ? 1 1
    ? 1 2
     
    Sample Output
    3
    2
    1
    6
    6
     
    题目大意:
      给出一棵树,边权均为1,有两种操作,改变某个点的权值,求距离某个点的距离不超过k的点的权值和.
     
    思路:
      这种动态的树分治问题我们应该这么想.
      想办法维护这个分治的结构,让它修改的速度变得快一些....
     
      于是我们这样子做.
      按照无修改的思路.我们要先全局计算,然后再减掉单独的子树内的重复信息.
      不难想到用树状数组来解决这个问题.
      为了方便找到全局和子树内的信息,每个点要维护两个树状数组.
      一个是这个点的子树内的信息,另外一个是这个点的子树内的点到上一层的中心点中的距离.
      这样我们就能在O(nlog2n)的时间内完成对一次询问的回答.
      然后注意.这个做法的复杂度的保证是基于两个中心点之间的距离的距离是O(logn)的.
      在另外一篇博文上吧这个做法称之为"重心树"还是蛮恰当的.
     
      我的程序参考了那篇博文的标程....凑合着看吧.
      Ps:一个大惑不解的问题.两个差不多的程序,为什么一个爆栈了呢?
      
      1 #include<cstdlib>
      2 #include<cstdio>
      3 #include<algorithm>
      4 #include<cstring>
      5 #include<vector>
      6 #include<cctype>
      7 using namespace std;
      8 const int maxn = (int)3e5, inf = 0x3f3f3f3f;
      9 struct E{
     10     int t,w,last;
     11 }e[maxn * 4];
     12 struct EE{
     13     int rt,srt,dis,last;
     14 }ee[maxn * 6];
     15 int ll[maxn * 6],edge;
     16 int last[maxn * 4],edg;
     17 int n,q;
     18 inline int getint(){
     19     int ret = 0; char ch = getchar();
     20     while(!isdigit(ch)) ch = getchar();
     21     while(isdigit(ch)) ret = ret * 10 + ch - '0', ch = getchar();
     22     return ret;
     23 }
     24 inline void add2(int x,int rt,int srt,int dis){
     25     ee[++edge] = (EE){rt,srt,dis,ll[x]}; ll[x] = edge;
     26 }
     27 inline void add(int x,int y,int w){
     28     e[++edg] = (E){y,w,last[x]}; last[x] = edg;
     29     e[++edg] = (E){x,w,last[y]}; last[y] = edg;
     30 }
     31 int w[maxn];
     32 int vis[maxn];
     33 int sz[maxn],tmax,node,root;
     34 void getroot(int x,int fa){
     35     sz[x] = 0;
     36     int Max = 0;
     37     for(int i = last[x]; i; i = e[i].last)
     38         if(!vis[e[i].t] && e[i].t != fa){
     39             getroot(e[i].t, x);
     40             sz[x] += sz[e[i].t] + 1;
     41             Max = max(Max, sz[e[i].t] + 1);
     42         }
     43     Max = max(Max, node - sz[x] - 1);
     44     if(tmax > Max) tmax = Max, root = x;
     45 }
     46 struct BIT{
     47     vector<int>v;
     48     void init(int sz){
     49         v.clear(); v.resize(sz + 2);
     50     }
     51     inline int lowbit(int x){
     52         return x & (-x);
     53     }    
     54     void add(int pos,int val){
     55         for(++pos; pos < (int)v.size(); pos += lowbit(pos)) v[pos] += val;
     56     }
     57     int qer(int pos){
     58         pos = min(pos + 1, (int)v.size() - 1);
     59         int ret = 0;
     60         for(; pos > 0; pos -= lowbit(pos)) ret += v[pos];
     61         return ret;
     62     }
     63 }T[maxn * 3];
     64 int cur;
     65 int rt,srt,dist;
     66 void getdata(int pt,int k, int x, int fa, int dis){
     67     if(k) add2(x,k,pt,dis);
     68     T[pt].add(dis, w[x]);
     69     for(int i = last[x]; i; i = e[i].last)
     70         if(!vis[e[i].t] && e[i].t != fa)
     71             getdata(pt, k, e[i].t, x, dis + e[i].w);
     72 }
     73 void dfs(int x,int size){
     74     int p;
     75     T[p = ++cur].init(size);
     76     getdata(p, 0, x, 0, 0);
     77     add2(x, p, 0, 0);
     78     vis[x] = 1;
     79     for(int i = last[x]; i; i = e[i].last)
     80         if(!vis[e[i].t]){
     81             tmax = inf, node = sz[e[i].t];
     82             getroot(e[i].t, root = 0);
     83             T[++cur].init(sz[e[i].t] + 1);
     84             getdata(cur, p, e[i].t, 0, e[i].w);
     85             dfs(root,sz[e[i].t]);
     86         }
     87 }
     88 void work(){
     89     tmax = inf, node = n;
     90     getroot(1,root = 0);
     91     dfs(root,n);
     92 }
     93 void query(){
     94     int x = getint(), d = getint();
     95     int ret = 0;
     96     for(int i = ll[x]; i; i = ee[i].last){
     97         int rt = ee[i].rt, srt = ee[i].srt, dis = ee[i].dis;
     98         ret += T[rt].qer(d - dis);
     99         if(srt) ret -= T[srt].qer(d - dis);
    100     }
    101     printf("%d
    ",ret);
    102 }
    103 void maintain(){
    104     int x = getint(), ww = getint();
    105     for(int i = ll[x]; i; i = ee[i].last){
    106         int rt = ee[i].rt,srt = ee[i].srt,dis = ee[i].dis;
    107         T[rt].add(dis, ww - w[x]);
    108         if(srt) T[srt].add(dis, ww - w[x]);
    109     }
    110     w[x] = ww;
    111 }
    112 void solve(){
    113     char op;
    114     while(q--){
    115         scanf("%c
    ",&op);
    116         if(op == '?') query();
    117         else maintain();
    118     }
    119 }
    120 void init(){
    121     memset(vis,0,sizeof(vis));
    122     memset(last,0,sizeof(last));
    123     memset(ll,0,sizeof(ll));
    124     cur = edge = edg = 0;
    125 }
    126 int main()
    127 {
    128     freopen("subtree.in","r",stdin);
    129     freopen("subtree.out","w",stdout);
    130     while(scanf("%d %d",&n,&q) != EOF){
    131         for(int i = 1; i <= n; ++i) w[i] = getint();
    132         for(int i = 1; i < n; ++i){
    133             int u = getint(), v = getint();
    134             add(u,v,1);
    135         }
    136         work();
    137         solve();
    138         init();
    139     }
    140     return 0;
    141 }
    View Code
  • 相关阅读:
    Class的一些使用技巧?
    简述tcp和udp的区别?
    java中list和map详解
    $(this) 和 this 关键字在 jQuery 中有何不同?
    多维数组转一维数组
    纯CSS画基本图形
    2020前端面试题个人收藏
    最简单的移动端适配方案(rem+vw)--没有之一
    http-serve开启一个服务器
    微信小程序端 Provisional headers are shown
  • 原文地址:https://www.cnblogs.com/Mr-ren/p/4215523.html
Copyright © 2020-2023  润新知