[JLOI2014]松鼠的新家-树链剖分

Posted wangyifan124

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[JLOI2014]松鼠的新家-树链剖分相关的知识,希望对你有一定的参考价值。

最开始的时候我在写线段树部分的时候还打了一个build,后来一想,打个球球大作战的build啊!!!有个锤子的用啊!!!

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 const int maxn = 3e6+5;
  4 int n;
  5 int e,begin[maxn],next[maxn],to[maxn],a[maxn];
  6 int tree[maxn<<2],lazy[maxn<<2];
  7 int son[maxn],father[maxn],id[maxn],cnt,deep[maxn],size[maxn],top[maxn];
  8 int res;
  9 inline int read(){
 10    int s=0,w=1;
 11    char ch=getchar();
 12    while(ch<=0||ch>9){if(ch==-)w=-1;ch=getchar();}
 13    while(ch>=0&&ch<=9) s=s*10+ch-0,ch=getchar();
 14    return s*w;
 15 }
 16 inline void add(int x,int y){
 17     to[++e] = y;
 18     next[e] = begin[x];
 19     begin[x] = e;
 20 }
 21 inline void pushup(int root){
 22     tree[root] = tree[root<<1]+tree[root<<1|1];
 23 }
 24 inline void pushdown(int root,int pos){
 25     lazy[root<<1] += lazy[root];
 26     lazy[root<<1|1] += lazy[root];
 27     tree[root<<1] += lazy[root]*(pos-(pos>>1));
 28     tree[root<<1|1] += lazy[root]*(pos>>1);
 29     lazy[root] = 0;
 30 }
 31 inline void query(int root,int l,int r,int al,int ar){
 32     if(al <= l && ar >= r){
 33         res += tree[root]; 
 34         return;
 35     }
 36     if(lazy[root])pushdown(root,r-l+1);
 37     int mid = l+r>>1;
 38     if(al <= mid)query(root<<1,l,mid,al,ar);
 39     if(ar > mid)query(root<<1|1,mid+1,r,al,ar);
 40 }
 41 inline void update(int root,int l,int r,int al,int ar,int k){
 42     if(al <= l && ar >= r){
 43         lazy[root] += k;
 44         tree[root] += k*(r-l+1);
 45         return;
 46     }
 47     if(lazy[root])pushdown(root,r-l+1);
 48     int mid = l+r>>1;
 49     if(al <= mid)update(root<<1,l,mid,al,ar,k);
 50     if(ar > mid)update(root<<1|1,mid+1,r,al,ar,k);
 51     pushup(root);
 52 }
 53 inline void update_range(int x,int y,int k){
 54     while(top[x] != top[y]){
 55         if(deep[top[x]] < deep[top[y]])swap(x,y);
 56         update(1,1,n,id[top[x]],id[x],k);
 57         x = father[top[x]];
 58     }
 59     if(deep[x] > deep[y])swap(x,y);
 60     update(1,1,n,id[x],id[y],k);
 61 }
 62 inline void dfs1(int x,int fa,int dep){
 63     deep[x] = dep;
 64     father[x] = fa;
 65     size[x] = 1;
 66     int maxson = -1;
 67     for(int i = begin[x];i;i = next[i]){
 68         int y = to[i];
 69         if(y == fa)continue;
 70         dfs1(y,x,dep+1);
 71         size[x] += size[y];
 72         if(size[y] > maxson)son[x] = y,maxson = size[y];
 73     }
 74 }
 75 inline void dfs2(int x,int topf){
 76     id[x] = ++cnt;
 77     top[x] = topf;
 78     if(!son[x])return;
 79     dfs2(son[x],topf);
 80     for(int i = begin[x];i;i = next[i]){
 81         int y = to[i];
 82         if(y == father[x] || y == son[x])continue;
 83         dfs2(y,y);
 84     }
 85 }
 86 int main(){
 87     n = read();
 88     for(int i = 1;i <= n;i++)a[i] = read();
 89     for(int i = 1,x,y;i < n;i++){
 90         x = read();
 91         y = read();
 92         add(x,y);
 93         add(y,x);
 94     }
 95     dfs1(1,0,1);
 96     dfs2(1,1);
 97     for(int i = 1;i < n;i++){
 98         update_range(a[i],a[i+1],1);
 99         update_range(a[i+1],a[i+1],-1);
100     }
101     for(int i = 1;i <= n;i++)res = 0,query(1,1,n,id[i],id[i]),printf("%d
",res);
102     return 0;
103 }

 

以上是关于[JLOI2014]松鼠的新家-树链剖分的主要内容,如果未能解决你的问题,请参考以下文章

「JLOI2014」松鼠的新家

Luogu P3258[JLOI2014]松鼠的新家

松鼠的新家 (lca+树上差分)或(树链剖分)

[Luogu 3258] JLOI2014 松鼠的新家

[JLOI2014]松鼠的新家

[JLOI2014]松鼠的新家 (树剖)