zoukankan      html  css  js  c++  java
  • bzoj3730:震波

    题意:给一棵树,只有点权无边权, ,每次询问求以一个点为中心,半径为k的全职和。

    考虑动态树分治。我们对于每个点(点分树)维护两个树状数组。两个树状数组都以距离为下标,权值为内容。第一个树状数组维护子树中距离该点为k的权值和,第二个维护距离该点父亲距离为k的权值和。这样改权值时我们暴力爬树高,loglog复杂度(log的树高加上log的树状数组)。查询的时候一样爬树高,要注意容斥(把当前子树k的先加起来,往祖先上爬,如果距离小于k,假设为d,我们到祖先上去求一个k-d,再容斥掉原来这棵子树里被计算过的,这就是第二个树状数组的用处)。

    时间复杂度0(nloglog),空间复杂度O(nlog)(如果用线段树还要加一个log。这里BB一句,为什么树状数组不会爆呢,因为你每一层开的大小为子树大小的话,每层总和n,总共log层,空间就是nlog的。其实就跟点分治的时间复杂度证明一样。用vector来开并且加上函数resize()就可以办到了。)

    这道题花了整整一天才写出来。。。一直RE(实际是WA,毕竟防离线加密,如果答案错了后面输入都是错的),总结一下错误:

    1.想的只用一个树状数组维护,实际上为了容斥必须要用上第二个树状数组。

    2.更新时,一开始要把自己丢在自己的第二个树状数组里面

    3.2这玩意肯定要写在爬树循环外面啊(你是SB吗)

    4.应该用qsum而不是query去爬树高(一开始脑袋抽了。。)

    5.往树上爬的时候是不会中途退出的,不会因为有一个祖先爬不上去就终止,说不定有一个爷爷就在你旁边你可以过去呢。

    对于点分树的题就想象成爬山吧,我们用每一层的重心将点们分割开来,每次爬树高都是解锁区域,翻过一座高山。

    还有,点分树自己脑补的板子实在太丑陋了。。这里膜拜一下ihopenot大佬,板子神快,我一开始好不容易调出来T了,参考了一下大佬的板子后就rank8了,真乃神人也!

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 100005
     4 #define INF 1e9
     5 #define lowbit(i) ((i)&-(i))
     6 int n,m,head[N],val[N],fa[N][20],dis[N][20],s[N],f[N],dep[N],rt,sz,cnt,ans;
     7 bool vis[N];
     8 vector<int>bit[N],fbit[N];
     9 inline int read(){
    10     int x=0,f=1; char a=getchar();
    11     while(a>'9' || a<'0') {if(a=='-') f=-1; a=getchar();}
    12     while(a<='9' && a>='0') x=x*10+a-'0',a=getchar();
    13     return x*f;
    14 } 
    15 struct edges{
    16     int to,next;
    17 }e[2*N];
    18 inline void insert(){
    19     int u=read(),v=read();
    20     e[cnt]=(edges){v,head[u]};head[u]=cnt++;
    21     e[cnt]=(edges){u,head[v]};head[v]=cnt++;
    22 }
    23 void getroot(int x,int father){
    24     s[x]=1; f[x]=0;
    25     for(int i=head[x];i>=0;i=e[i].next){
    26         if(vis[e[i].to] || father==e[i].to) continue;
    27         getroot(e[i].to,x); s[x]+=s[e[i].to];
    28         f[x]=max(f[x],s[e[i].to]);
    29     }
    30     f[x]=max(f[x],sz-s[x]);
    31     if(f[x]<f[rt]) rt=x;
    32 }
    33 void getship(int x,int anc,int father,int d){
    34     for(int i=head[x];i>=0;i=e[i].next){
    35      int v=e[i].to;
    36      if(!vis[v] && v!=father) fa[v][++dep[v]]=anc,dis[v][dep[v]]=d,getship(v,anc,x,d+1);
    37     }
    38 }
    39 void Buildtree(int x){
    40     vis[x]=1; getship(x,x,0,1); 
    41     int all=sz; bit[x].resize(all+1); fbit[x].resize(all+1);
    42     for(int i=head[x];i>=0;i=e[i].next){
    43         if(vis[e[i].to]) continue;
    44         sz=s[e[i].to]; if(sz>s[x]) sz=all-s[x];
    45         rt=0; getroot(e[i].to,x); Buildtree(rt);
    46     }
    47 }
    48 inline int qsum(int x,int k){
    49     int ret=val[x],lim=bit[x].size()-1; k=min(k,lim); 
    50     for(int i=k;i;i-=lowbit(i)) ret+=bit[x][i];
    51     return ret;
    52 }
    53 inline int qsum2(int x,int k){
    54     int ret=0,lim=fbit[x].size()-1; k=min(k,lim);
    55     for(int i=k;i;i-=lowbit(i)) ret+=fbit[x][i];
    56     return ret;
    57 }
    58 inline void change(int x,int v){
    59     int d,lim; 
    60     d=dis[x][dep[x]]; lim=bit[x].size()-1;
    61     for(int j=d;j<=lim && j;j+=lowbit(j)) fbit[x][j]+=v;
    62     for(int i=dep[x];i;i--){
    63         d=dis[x][i]; lim=bit[fa[x][i]].size()-1;
    64         for(int j=d;j<=lim;j+=lowbit(j)) bit[fa[x][i]][j]+=v;
    65         d=dis[x][i-1];
    66         for(int j=d;j<=lim && j;j+=lowbit(j)) fbit[fa[x][i]][j]+=v;
    67     }
    68 }
    69 int query(int x,int k){
    70     int ret=qsum(x,k);
    71     for(int i=dep[x];i;i--) if(dis[x][i]<=k)
    72     ret+=qsum(fa[x][i],k-dis[x][i])-qsum2(fa[x][i+1],k-dis[x][i]);
    73     return ret;
    74 }
    75 int main(){
    76     n=read(); m=read(); memset(head,-1,sizeof(head));
    77     for(int i=1;i<=n;i++) val[i]=read();
    78     for(int i=1;i<n;i++) insert();
    79     f[0]=INF; sz=n; getroot(1,0); Buildtree(rt); 
    80     for(int i=1;i<=n;i++) fa[i][dep[i]+1]=i;
    81     for(int i=1;i<=n;i++) change(i,val[i]);
    82     while(m--){
    83         int a=read(),b=read()^ans,c=read()^ans;
    84         if(!a) ans=query(b,c),printf("%d
    ",ans);
    85         else change(b,c-val[b]),val[b]=c;
    86     }
    87     return 0;
    88 }
  • 相关阅读:
    SPOJ 694 (后缀数组) Distinct Substrings
    POJ 2774 (后缀数组 最长公共字串) Long Long Message
    POJ 3693 (后缀数组) Maximum repetition substring
    POJ 3261 (后缀数组 二分) Milk Patterns
    UVa 1149 (贪心) Bin Packing
    UVa 12206 (字符串哈希) Stammering Aliens
    UVa 11210 (DFS) Chinese Mahjong
    UVa (BFS) The Monocycle
    UVa 11624 (BFS) Fire!
    HDU 3032 (Nim博弈变形) Nim or not Nim?
  • 原文地址:https://www.cnblogs.com/enigma-aw/p/6209545.html
Copyright © 2011-2022 走看看