zoukankan      html  css  js  c++  java
  • 洛谷 P2590 [ZJOI2008]树的统计(线段树,树链剖分)

    传送门


    解题思路

    关于两点之间的最短距离的区间操作,很显然是树链剖分

    因为既有区间和还有区间最大值,所以我们建立两个线段树。

    然后就是树剖的常规操作了。

    AC代码

      1 #include<iostream>
      2 #include<algorithm>
      3 #include<cmath>
      4 #include<cstdio>
      5 #include<cstring>
      6 #include<iomanip>
      7 using namespace std;
      8 const int maxn=100005;
      9 int n,q,v[maxn],cnt,dep[maxn],siz[maxn],tp[maxn],son[maxn],f[maxn];
     10 int s1[maxn*4],s2[maxn*4],p[maxn];
     11 int id[maxn],rk[maxn];
     12 struct Edge{
     13     int v,next;
     14 }e[maxn];
     15 void insert(int u,int v){
     16     cnt++;
     17     e[cnt].v=v;
     18     e[cnt].next=p[u];
     19     p[u]=cnt;
     20 }
     21 void dfs1(int fa,int u,int deep){
     22     f[u]=fa;
     23     dep[u]=deep;
     24     siz[u]=1;
     25     for(int i=p[u];i!=-1;i=e[i].next){
     26         if(e[i].v==fa) continue;
     27         dfs1(u,e[i].v,deep+1);
     28         siz[u]+=siz[e[i].v];
     29         if(siz[e[i].v]>siz[son[u]]) son[u]=e[i].v;
     30     }
     31 }
     32 void dfs2(int fa,int u,int top){
     33     tp[u]=top;
     34     cnt++;
     35     id[u]=cnt;
     36     rk[cnt]=u;
     37     if(!son[u]) return;
     38     dfs2(u,son[u],top);
     39     for(int i=p[u];i!=-1;i=e[i].next){
     40         if(e[i].v==son[u]||e[i].v==fa) continue;
     41         dfs2(u,e[i].v,e[i].v);
     42     }
     43 }
     44 void build(int id,int l,int r){
     45     if(l==r){
     46         s1[id]=s2[id]=v[rk[l]];
     47         return;
     48     }
     49     int mid=(l+r)/2;
     50     build(id*2,l,mid);
     51     build(id*2+1,mid+1,r);
     52     s1[id]=s1[id*2]+s1[id*2+1];
     53     s2[id]=max(s2[id*2],s2[id*2+1]);
     54 }
     55 void add(int id,int x,int l,int r,int value){
     56     if(l==r){
     57         s1[id]=value;
     58         s2[id]=value;
     59         return;
     60     }
     61     int mid=(l+r)/2;
     62     if(x<=mid) add(id*2,x,l,mid,value);
     63     if(x>mid)  add(id*2+1,x,mid+1,r,value);
     64     s1[id]=s1[id*2]+s1[id*2+1];
     65     s2[id]=max(s2[id*2],s2[id*2+1]);
     66 }
     67 int querymax(int id,int x,int y,int l,int r){
     68     if(x<=l&&r<=y) return s2[id];
     69     int mid=(l+r)/2;
     70     int res=-9999999;
     71     if(x<=mid) res=max(res,querymax(id*2,x,y,l,mid));
     72     if(mid<y)  res=max(res,querymax(id*2+1,x,y,mid+1,r));
     73     return res; 
     74 }
     75 int querysum(int id,int x,int y,int l,int r){
     76     if(x<=l&&r<=y) return s1[id];
     77     int mid=(l+r)/2;
     78     int res=0;
     79     if(x<=mid) res+=querysum(id*2,x,y,l,mid);
     80     if(mid<y)  res+=querysum(id*2+1,x,y,mid+1,r);
     81     return res; 
     82 }
     83 int main()
     84 {
     85     memset(p,-1,sizeof(p));
     86     cin>>n;
     87     for(int i=1;i<n;i++){
     88         int a,b;
     89         cin>>a>>b;
     90         insert(a,b);
     91         insert(b,a);
     92     }
     93     for(int i=1;i<=n;i++) cin>>v[i];
     94     dfs1(-1,1,1);
     95     cnt=0;
     96     dfs2(-1,1,1);
     97     build(1,1,n);
     98     cin>>q;
     99     for(int i=1;i<=q;i++){
    100         string s;
    101         int a,b;
    102         cin>>s>>a>>b;
    103         if(s=="CHANGE"){
    104             add(1,id[a],1,n,b);
    105         }else{
    106             if(s=="QSUM"){
    107                 int ans=0;
    108                 while(tp[a]!=tp[b]){
    109                     if(dep[tp[a]]<dep[tp[b]]) swap(a,b);
    110                     ans+=querysum(1,id[tp[a]],id[a],1,n);
    111                     a=f[tp[a]];
    112                 }
    113                 if(dep[a]<dep[b]) swap(a,b);
    114                 ans+=querysum(1,id[b],id[a],1,n);
    115                 cout<<ans<<endl;
    116             }else{
    117                 int ans=-9999999;
    118                 while(tp[a]!=tp[b]){
    119                     if(dep[tp[a]]<dep[tp[b]]) swap(a,b);
    120                     ans=max(ans,querymax(1,id[tp[a]],id[a],1,n));
    121                     a=f[tp[a]];
    122                 }
    123                 if(dep[a]<dep[b]) swap(a,b);
    124                 ans=max(ans,querymax(1,id[b],id[a],1,n));
    125                 cout<<ans<<endl;
    126             }
    127         }
    128     }    
    129     return 0;
    130 }
  • 相关阅读:
    【每天都要看一下】
    【这里有别人的经验,也有好玩的发现】
    【WPF】Listbox模板内button点击选中当前listboxItem
    【WFP】弹出窗口不在win10 任务列表里显示的方法
    PSD路径转换为 WPF path 的data
    【WPF】Listbox内item的样式替换默认选中样式和鼠标滑过样式
    【WPF】ListBox1内嵌套ListBox2 2的滑轮滚动阻止1的滚动解决方法
    【C#】文本框拼音检索汉字
    【WPF】Datagrid显示最低下一跳
    【C#】绝对随机数
  • 原文地址:https://www.cnblogs.com/yinyuqin/p/13286325.html
Copyright © 2011-2022 走看看