今天学习了树链剖分并且做了几道很有意思的题。。。

      树链剖分的大致思想就是把一棵树转化成一条链(一个序列),然

后在上面做一些处理,例如:线段树。树转链的方法大致类似于 dfs

序,但是多了一个重边的处理。

      上水题。(题名自行google)

      1.BZOJ1036 ZJOJ2008 树的统计Count

      标准模板题,超级水0.0。。。。。。

CODE:

 

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<stack>
  4 #include<queue>
  5 #include<cstring>
  6 #include<algorithm>
  7 #include<vector>
  8 #include<cmath>
  9 #define inf 0x3f3f3f3f
 10 #define ll long long
 11 #define maxn  30005
 12 #define lson u<<1,l,mid
 13 #define rson u<<1|1,mid+1,r
 14 using namespace std;
 15 int w[maxn],head[maxn],tid[maxn],size[maxn],id[maxn],fa[maxn],son[maxn],dep[maxn],top[maxn],ecnt=1,cnt;
 16 
 17 struct edge{
 18     int v,next;
 19 }e[maxn*2];
 20 
 21 void adde(int u,int v){
 22     e[ecnt].v=v;
 23     e[ecnt].next=head[u];
 24     head[u]=ecnt++;
 25 }
 26 
 27 void dfs1(int u,int pre){
 28     dep[u]=dep[pre]+1;
 29     fa[u]=pre;
 30     size[u]=1;
 31     int msum=0;
 32     for(int i=head[u];i;i=e[i].next){
 33         int v=e[i].v;
 34         if(v==pre)continue;
 35         dfs1(v,u);
 36         size[u]+=size[v];
 37         if(size[v]>msum){
 38             msum=size[v];
 39             son[u]=v;
 40         }
 41     }
 42 }
 43 
 44 void dfs2(int u,int anc){
 45     tid[u]=++cnt;
 46     top[u]=anc;
 47     id[cnt]=u;
 48     if(son[u])dfs2(son[u],anc);
 49     for(int i=head[u];i;i=e[i].next){
 50         int v=e[i].v;
 51         if(v==son[u]||v==fa[u])continue;
 52         dfs2(v,v);
 53     }
 54 }
 55 
 56 struct node{
 57     int l,r,ma,sum;
 58 }t[4*maxn];
 59 
 60 void update(int u){
 61     t[u].sum=t[u<<1].sum+t[u<<1|1].sum;
 62     t[u].ma=max(t[u<<1].ma,t[u<<1|1].ma);
 63 }
 64 
 65 void build(int u,int l,int r){
 66     t[u].l=l;
 67     t[u].r=r;
 68     if(l==r){
 69         t[u].sum=t[u].ma=w[id[l]];
 70         return;
 71     }
 72     int mid=(l+r)>>1;
 73     build(lson);
 74     build(rson);
 75     update(u);
 76 }
 77 
 78 int askmax(int u,int l,int r){
 79     if(t[u].r==r&&t[u].l==l)return t[u].ma;
 80     int mid=(t[u].l+t[u].r)>>1;
 81     if(r<=mid)return askmax(u<<1,l,r);
 82     if(l>mid)return askmax(u<<1|1,l,r);
 83     else return max(askmax(u<<1,l,mid),askmax(u<<1|1,mid+1,r));
 84 }
 85 
 86 int asksum(int u,int l,int r){
 87     if(t[u].r==r&&t[u].l==l)return t[u].sum;
 88     int mid=(t[u].l+t[u].r)>>1;
 89     if(r<=mid)return asksum(u<<1,l,r);
 90     if(l>mid)return asksum(u<<1|1,l,r);
 91     else return asksum(u<<1,l,mid)+asksum(u<<1|1,mid+1,r);
 92 }
 93 
 94 int findsum(int u,int v){
 95     int fu=top[u],fv=top[v];
 96     int tmp=0;
 97     while(fu!=fv){
 98         if(dep[fu]<dep[fv]){
 99             swap(fu,fv);
100             swap(u,v);
101         }
102         tmp+=asksum(1,tid[fu],tid[u]);
103         u=fa[fu];
104         fu=top[u];
105     }
106     if(dep[u]>dep[v])swap(u,v);
107     return tmp+asksum(1,tid[u],tid[v]);
108 }
109 
110 int findmax(int u,int v){
111     int fu=top[u],fv=top[v];
112     int tmp=-99999999;
113     while(fu!=fv){
114         if(dep[fu]<dep[fv]){
115             swap(fu,fv);
116             swap(u,v);
117         }
118         tmp=max(tmp,askmax(1,tid[fu],tid[u]));
119         u=fa[fu];
120         fu=top[u];
121     }
122     if(dep[u]>dep[v])swap(u,v);
123     return max(tmp,askmax(1,tid[u],tid[v]));
124 }
125 
126 void change(int u,int k,int val){
127     if(t[u].l==k&&t[u].r==k){
128         t[u].ma=t[u].sum=val;
129         return;
130     }
131     int mid=(t[u].l+t[u].r)>>1;
132     if(k<=mid)change(u<<1,k,val);
133     else change(u<<1|1,k,val);
134     update(u);
135 }
136 
137 int main(){
138     int n,m;
139     scanf("%d",&n);
140     int a,b;
141     for(int i=1;i<n;i++)scanf("%d%d",&a,&b),adde(a,b),adde(b,a);
142     for(int i=1;i<=n;i++)scanf("%d",&w[i]),t[i].ma=-99999999;
143     dfs1(1,0);
144     dfs2(1,1);
145     build(1,1,n);
146     scanf("%d",&m);
147     for(int i=1;i<=m;i++){
148         char s[100];
149         scanf("%s",s);
150         scanf("%d%d",&a,&b);
151         if(s[0]=='C')change(1,tid[a],b);
152         else if(!strcmp(s,"QMAX"))printf("%d\n",findmax(a,b));
153         else printf("%d\n",findsum(a,b));
154     }
155     return 0;
156 }
想不想看???

相关文章:

  • 2021-08-03
  • 2021-11-22
  • 2021-08-21
  • 2021-09-09
  • 2021-12-20
  • 2022-01-13
  • 2021-12-06
  • 2021-09-20
猜你喜欢
  • 2022-12-23
  • 2022-02-02
  • 2022-12-23
  • 2022-01-31
  • 2021-11-22
  • 2021-06-14
  • 2022-02-02
相关资源
相似解决方案