zoukankan      html  css  js  c++  java
  • HZOJ Tree

    看到换根果断lct啊,然而其实我板子还没有打熟,还不会维护子树信息,于是就挂掉了……

    然而正解并不是lct。

    其实好像很久很久以前将lca的时候好像讲到过一道换根的题,当时没有听懂。

    直接说正解吧:

    把dfs序搞出来用线段树维护。

    用一个变量记录当前根节点,操作一直接改就行了。

    然后是操作三:

    分情况讨论,设当前根节点为root,询问的点为a。

    如果root不在a的子树内,那么root不会影响a的子树,仍然输出1为根时的子树和就行了。

    如果在子树内,

    如图,如果要查询1的子树和,那么找到1与root这条链上靠近1的点,整体的和减去这个点的子树和就是了。(感性理解一下。)

    那么这个点怎么求呢?只需要对于每个点把与他直接相连的儿子的dfs序塞到一个vector里,upper_bound然后-1就可以了。

    操作二:

    首先求出以1为根是a,b两点的lca。

    与操作三类似,如果root不在lca的子树内,那么root不会影响lca,直接加就行。

    如果在子树内,那么找a,b与root的lca中深度较大的那个。

    之后就和操作三一样了。

      1 #include<algorithm>
      2 #include<iostream>
      3 #include<cstring>
      4 #include<cstdio>
      5 #include<vector>
      6 #define LL long long
      7 #define re register
      8 #define co const
      9 #define rec re co
     10 #define inline __attribute((always_inline))
     11 const int LLL=1<<20|1;
     12 char buffer[LLL],*S,*TT;
     13 #define getchar() ((S==TT&&(TT=(S=buffer)+fread(buffer,1,LLL,stdin),S==TT))?EOF:*S++)
     14 using namespace std;
     15 struct edge
     16 {
     17     int u,v,nxt;
     18     #define u(x) ed[x].u
     19     #define v(x) ed[x].v
     20     #define n(x) ed[x].nxt
     21 }ed[1000010];
     22 int first[300010],num_e;
     23 #define f(x) first[x]
     24 int n,q,w[300010];
     25 bool pd2=1,pd3=1;
     26 vector<int> inc[300010];
     27 LL fa[300010][21],dep[300010];
     28 int dfn[300010],id[300010],cnt,L[300010],R[300010];LL res;
     29 int siz[300010],son[300010],top[300010];
     30 void dfs1(int x)
     31 {
     32     siz[x]=1;
     33     for(int i=f(x);i;i=n(i))
     34     if(v(i)!=fa[x][0])
     35     {
     36         fa[v(i)][0]=x;dep[v(i)]=dep[x]+1;
     37         dfs1(v(i));siz[x]+=siz[v(i)];
     38         if(siz[v(i)]>siz[son[x]])son[x]=v(i);
     39     }
     40 }
     41 void dfs2(int x,int t)
     42 {
     43     top[x]=t;dfn[x]=++cnt;id[cnt]=x;L[x]=cnt;
     44     if(son[x])dfs2(son[x],t),inc[x].push_back(dfn[son[x]]);
     45     for(int i=f(x);i;i=n(i))
     46     if(v(i)!=fa[x][0]&&v(i)!=son[x])
     47     dfs2(v(i),v(i)),inc[x].push_back(dfn[v(i)]);
     48     R[x]=cnt;
     49 }
     50 inline int LCA(int x,int y)
     51 {
     52     while(top[x]!=top[y])
     53     {
     54         if(dep[top[x]]>dep[top[y]])swap(x,y);
     55         y=fa[top[y]][0];
     56     }
     57     if(dep[x]>dep[y])swap(x,y);
     58     return x;
     59 }
     60 struct xjs_Tree
     61 {
     62     struct tree
     63     {
     64         int l,r;LL sum,la;
     65         #define l(x) tr[x].l
     66         #define r(x) tr[x].r
     67         #define la(x) tr[x].la
     68         #define sum(x) tr[x].sum 
     69         #define ls(x) ((x)<<1)
     70         #define rs(x) (ls(x)+1)
     71     }tr[8000000];
     72     void build(rec int x,rec int l,rec int r)
     73     {
     74         l(x)=l,r(x)=r,la(x)=0;
     75         if(l==r){sum(x)=w[id[l]];return;}
     76         int mid=(l+r)>>1;
     77         build(ls(x),l,mid);
     78         build(rs(x),mid+1,r);
     79         sum(x)=sum(ls(x))+sum(rs(x));
     80     }
     81     inline void down(rec int x)
     82     {    
     83         if(l(x)==r(x))return;
     84         if(!la(x))return;
     85         sum(ls(x))+=(r(ls(x))-l(ls(x))+1)*la(x);
     86         sum(rs(x))+=(r(rs(x))-l(rs(x))+1)*la(x);
     87         la(ls(x))+=la(x);la(rs(x))+=la(x);la(x)=0;
     88     }
     89     void add(rec int x,rec int l,rec int r,rec LL y)
     90     {
     91         if(l>r)return;
     92         down(x);
     93         if(l(x)>=l&&r(x)<=r)
     94         {
     95             sum(x)+=(r(x)-l(x)+1)*y;
     96             la(x)+=y;return;
     97         }    
     98         int mid=(l(x)+r(x))>>1;
     99         if(l<=mid)add(ls(x),l,r,y);
    100         if(r> mid)add(rs(x),l,r,y);
    101         sum(x)=sum(ls(x))+sum(rs(x));
    102     }
    103     LL ask(rec int x,rec int l,rec int r)
    104     {
    105         if(l>r)return 0;
    106         down(x);
    107         if(l(x)>=l&&r(x)<=r)return sum(x);
    108         int mid=(l(x)+r(x))>>1;LL ans=0;
    109         if(l<=mid)ans+=ask(ls(x),l,r);
    110         if(r> mid)ans+=ask(rs(x),l,r);
    111         return ans;
    112     }
    113 }T;
    114 inline int read();
    115 inline void add(rec int u,rec int v);
    116 signed main()
    117 {    
    118 //    freopen("S1_1.in","r",stdin);
    119 //    freopen("in.txt","r",stdin);
    120 //    freopen("1.out","w",stdout);
    121     
    122     n=read(),q=read();int tu,tv;
    123     for(re int i=1;i<=n;i++)w[i]=read();
    124     for(re int i=1;i<n;i++)tu=read(),tv=read(),add(tu,tv),add(tv,tu);
    125     re int root=1;
    126     dep[1]=1;dfs1(1),dfs2(1,1);T.build(1,1,n);
    127     re int opt,a,b,c;
    128     for(re int i=1;i<=q;i++)
    129     {
    130         opt=read();
    131         if(opt==1)a=read(),root=a;
    132         if(opt==2)
    133         {
    134             a=read(),b=read(),c=read();
    135             int lca=LCA(a,b);
    136             if(lca==root)T.add(1,1,n,c);
    137             else if(dfn[root]<L[lca]||dfn[root]>R[lca])T.add(1,L[lca],R[lca],c);
    138             else
    139             {
    140                 int t1=LCA(a,root),t2=LCA(b,root);
    141                 if(dep[t1]>dep[t2])lca=t1;
    142                 else lca=t2;
    143                 if(lca==root)T.add(1,1,n,c);
    144                 else if(dfn[root]<L[lca]||dfn[root]>R[lca])T.add(1,L[lca],R[lca],c);
    145                 else 
    146                 {
    147                     int te=upper_bound(inc[lca].begin(),inc[lca].end(),dfn[root])-inc[lca].begin()-1;
    148                     lca=inc[lca][te];lca=id[lca];
    149                     T.add(1,1,L[lca]-1,c),T.add(1,R[lca]+1,n,c);
    150                 }
    151             }
    152         }
    153         if(opt==3)
    154         {    
    155             a=read();
    156             if(a==root)printf("%lld
    ",T.ask(1,1,n));
    157             else if(dfn[root]<L[a]||dfn[root]>R[a])printf("%lld
    ",T.ask(1,L[a],R[a]));
    158             else 
    159             {
    160                 int te=upper_bound(inc[a].begin(),inc[a].end(),dfn[root])-inc[a].begin()-1;
    161                 te=inc[a][te];te=id[te];
    162                 printf("%lld
    ",T.ask(1,1,L[te]-1)+T.ask(1,R[te]+1,n));
    163             }
    164         }
    165     }
    166     return 0;
    167 }
    168 inline int read()
    169 {
    170     int s=0,f=1;char a=getchar();
    171     while(a<'0'||a>'9'){if(a=='-')f=-1;a=getchar();}
    172     while(a>='0'&&a<='9'){s=s*10+a-'0';a=getchar();}
    173     return s*f;
    174 }
    175 inline void add(rec int u,rec int v)
    176 {
    177     ++num_e;
    178     u(num_e)=u;
    179     v(num_e)=v;
    180     n(num_e)=f(u);
    181     f(u)=num_e;
    182 }
    View Code
  • 相关阅读:
    Windows系统架构
    UVa10006-Carmichael Numbers
    Android打开系统设置
    C语言与汇编“硬在哪里”——什么是面向硬件?
    javaSocket与C通信
    小智慧25
    sqlplus中显示sql执行计划和统计信息
    记一次修复被篡改的IE首页
    UIView的生命周期
    [置顶] 关于UBUNTU 12.04, 在THINKPAD E430C上WIFI连接不上的问题
  • 原文地址:https://www.cnblogs.com/Al-Ca/p/11597858.html
Copyright © 2011-2022 走看看