• BZOJ 1036 [ZJOI2008]树的统计Count


    以前动态树写过这个题,今天尝试树链剖分解决~

    模板题,就声明一点,线段树维护的是点权

    View Code
      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <cstdlib>
      5 #include <algorithm>
      6 
      7 #define N 50000
      8 #define M 100000
      9 #define INF 1e9
     10 
     11 using namespace std;
     12 
     13 int head[N],to[M],next[M];
     14 int sz[N],top[N],bh[N],fa[N],son[N],dep[N];
     15 int sum[N<<2],mx[N<<2],val[N],dat[N];
     16 int q[N];
     17 int n,cnt,tot,qu;
     18 
     19 inline void add(int u,int v)
     20 {
     21     to[cnt]=v; next[cnt]=head[u]; head[u]=cnt++;
     22 }
     23 
     24 inline void prep()
     25 {
     26     int h=1,t=2,sta;
     27     q[1]=1; dep[1]=1;
     28     while(h<t)
     29     {
     30         sta=q[h++]; sz[sta]=1;
     31         for(int i=head[sta];~i;i=next[i])
     32             if(to[i]!=fa[sta])
     33             {
     34                 fa[to[i]]=sta;
     35                 dep[to[i]]=dep[sta]+1;
     36                 q[t++]=to[i];
     37             }
     38     }
     39     for(int j=t-1;j>=1;j--)
     40     {
     41         sta=q[j];
     42         for(int i=head[sta];~i;i=next[i])
     43             if(to[i]!=fa[sta])
     44             {
     45                 sz[sta]+=sz[to[i]];
     46                 if(sz[to[i]]>sz[son[sta]]) son[sta]=to[i]; 
     47             }
     48     }
     49     for(int i=1;i<t;i++)
     50     {
     51         sta=q[i];
     52         if(son[fa[sta]]==sta) top[sta]=top[fa[sta]];//不是重链顶部 
     53         else top[sta]=sta;
     54     }
     55 }
     56 
     57 inline void rewrite()
     58 {
     59     for(int i=1;i<=n;i++)
     60         if(top[i]==i)
     61             for(int j=i;j;j=son[j])//每条重链的编号是连续的 
     62             {
     63                 bh[j]=++tot;
     64                 dat[tot]=val[j];
     65             }
     66 }
     67 
     68 inline void pushup(int x)
     69 {
     70     sum[x]=sum[x<<1]+sum[x<<1|1];
     71     mx[x]=max(mx[x<<1],mx[x<<1|1]);
     72 }
     73 
     74 inline void build(int u,int L,int R)
     75 {
     76     if(L==R) {sum[u]=mx[u]=dat[L];return;}
     77     int MID=(L+R)>>1;
     78     build(u<<1,L,MID); build(u<<1|1,MID+1,R);
     79     pushup(u);
     80 }
     81 
     82 inline void read()
     83 {
     84     memset(head,-1,sizeof head); cnt=0;
     85     scanf("%d",&n);
     86     for(int i=1,a,b;i<n;i++)
     87     {
     88         scanf("%d%d",&a,&b);
     89         add(a,b); add(b,a);
     90     }
     91     for(int i=1;i<=n;i++) scanf("%d",&val[i]);
     92     prep();
     93     rewrite();
     94     build(1,1,tot);
     95 }
     96 
     97 inline int querysum(int u,int L,int R,int l,int r)
     98 {
     99     if(l<=L&&R<=r) return sum[u];
    100     int MID=(L+R)>>1,res=0;
    101     if(l<=MID) res+=querysum(u<<1,L,MID,l,r);
    102     if(MID<r) res+=querysum(u<<1|1,MID+1,R,l,r);
    103     return res;
    104 }
    105 
    106 inline int getsum(int x,int y)
    107 {
    108     int res=0;
    109     while(top[x]!=top[y])
    110     {
    111         if(dep[top[x]]<dep[top[y]]) swap(x,y);
    112         res+=querysum(1,1,tot,bh[top[x]],bh[x]);
    113         x=fa[top[x]];
    114     }
    115     if(bh[x]>bh[y]) swap(x,y);
    116     res+=querysum(1,1,tot,bh[x],bh[y]);
    117     return res;
    118 }
    119 
    120 inline int querymax(int u,int L,int R,int l,int r)
    121 {
    122     if(l<=L&&R<=r) return mx[u];
    123     int MID=(L+R)>>1,res=-INF;
    124     if(l<=MID) res=max(res,querymax(u<<1,L,MID,l,r));
    125     if(MID<r) res=max(res,querymax(u<<1|1,MID+1,R,l,r));
    126     return res;
    127 }
    128 
    129 inline int getmax(int x,int y)
    130 {
    131     int res=-INF;
    132     while(top[x]!=top[y])
    133     {
    134         if(dep[top[x]]<dep[top[y]]) swap(x,y);
    135         res=max(res,querymax(1,1,tot,bh[top[x]],bh[x]));
    136         x=fa[top[x]];
    137     }
    138     if(bh[x]>bh[y]) swap(x,y);
    139     
    140     res=max(res,querymax(1,1,tot,bh[x],bh[y]));
    141     return res; 
    142 }
    143 
    144 inline void updata(int u,int L,int R,int pos,int sp)
    145 {
    146     if(L==R) {mx[u]=sum[u]=sp;return;}
    147     int MID=(L+R)>>1;
    148     if(pos<=MID) updata(u<<1,L,MID,pos,sp);
    149     else updata(u<<1|1,MID+1,R,pos,sp);
    150     pushup(u);
    151 }
    152 
    153 inline void go()
    154 {
    155     scanf("%d",&qu);
    156     char str[10];int a,b;
    157     while(qu--)
    158     {
    159         scanf("%s%d%d",str,&a,&b);
    160         if(str[1]=='S') printf("%d\n",getsum(a,b));
    161         else if(str[1]=='M') printf("%d\n",getmax(a,b));
    162         else updata(1,1,tot,bh[a],b);
    163     }
    164 }
    165 
    166 int main()
    167 {
    168     read();
    169     go();
    170     return 0;
    171 } 
  • 相关阅读:
    20个最佳的Java集合框架面试题目
    SSL/TLS 加密新纪元
    NServiceBus-日志
    NServiceBus-容器
    NServiceBus-网关和多站点分布
    NServiceBus-性能测试
    NServiceBus教程-持久化配置
    NServiceBus教程-持久化
    NServiceBus教程-NServiceBus和WCF
    NServiceBus教程-消息传递与处理
  • 原文地址:https://www.cnblogs.com/proverbs/p/2867092.html
Copyright © 2020-2023  润新知