特技树链剖分

线段树划分时按照子树的size平分

听说会变成一个log的,实际效果不明

BZOJ1036

#include <cstdio>
#include <iostream>
#include <cmath>
#define LL long long 
using namespace std;
 
  struct treenode{
      LL sum,maxi;
      int mid,l,r,lc,rc;
  }tr[400001];
 
  int size[200001],nd[200001],next[400001],dep[200001],des[400001],fa[200001];
  int heav[200001],top[200001],ori[200001],cnt,id[200001];
  int a[200001],root[200001],n,t1,t2,dsize[200001];
  char st[201];
 
  void addedge(int x,int y){
     next[++cnt]=nd[x];des[cnt]=y;nd[x]=cnt;
  }
 
  void dfs1(int po){
      size[po]=1;int maxi=0;
      for (int p=nd[po];p!=-1;p=next[p])
        if (!dep[des[p]]){
            dep[des[p]]=dep[po]+1;
            fa[des[p]]=po;
            dfs1(des[p]);
            size[po]+=size[des[p]];
            if (size[des[p]]>maxi){
              maxi=size[des[p]];
              heav[po]=des[p];
        }
      }
  }
 
  void dfs2(int po,int tp){
      top[po]=tp;ori[++cnt]=po;id[po]=cnt;dsize[po]=1;
      if (heav[po]) dfs2(heav[po],tp);
      for (int p=nd[po];p!=-1;p=next[p])
        if (des[p]!=heav[po]&&dep[des[p]]==dep[po]+1){
          dfs2(des[p],des[p]);          
          dsize[po]+=size[des[p]];
        }
        
  }
 
  void update(int po){
    tr[po].maxi=max(tr[tr[po].lc].maxi,tr[tr[po].rc].maxi);
    tr[po].sum=tr[tr[po].lc].sum+tr[tr[po].rc].sum;
  }
 
  void build(int l,int r){
      tr[++cnt].l=l;tr[cnt].r=r;
      if (l==r){
        tr[cnt].sum=tr[cnt].maxi=a[ori[l]];
      return;    
    }
    
    int totd=0,mini=1e9,t=0;for (int i=l;i<=r;i++) totd+=dsize[ori[i]];
    for (int i=l;i<r;i++){
      t+=dsize[ori[i]];
      if (fabs(totd-2*t)<mini){
          mini=fabs(totd-2*t);
          tr[cnt].mid=i;
      }    
    }
    
    t=cnt;
    tr[t].lc=cnt+1;
    build(l,tr[t].mid);
    tr[t].rc=cnt+1;
    build(tr[t].mid+1,r);
    update(t);
  }
 
  void edi(int po,int tar,int num){
      if (tr[po].l==tr[po].r){
      tr[po].sum=tr[po].maxi=num;
      return;
    }
    
    if (tar<=tr[po].mid)
      edi(tr[po].lc,tar,num);else
      edi(tr[po].rc,tar,num);
    update(po);
  }
 
  LL segsum(int po,int tarl,int tarr){
      if (tarl==tr[po].l&&tarr==tr[po].r)
        return(tr[po].sum);    
      LL ret=0;
      if (tarl<=tr[po].mid)
        ret+=segsum(tr[po].lc,tarl,min(tr[po].mid,tarr));
      if (tarr>tr[po].mid)
        ret+=segsum(tr[po].rc,max(tr[po].mid+1,tarl),tarr);
      return(ret);
  }
 
  LL quesum(int x,int y){
      LL ret=0;
      while (top[x]!=top[y]){
        if (dep[top[x]]<dep[top[y]]) swap(x,y);
        ret+=segsum(root[top[x]],id[top[x]],id[x]);
        x=fa[top[x]];
    }
    if (dep[x]<dep[y]) swap(x,y);
    ret+=segsum(root[top[x]],id[y],id[x]);
    return(ret);
  }
  
  LL segmax(int po,int tarl,int tarr){
      if (tarl==tr[po].l&&tarr==tr[po].r)
        return(tr[po].maxi);    
      LL ret=-1e9;
      if (tarl<=tr[po].mid)
      ret=max(segmax(tr[po].lc,tarl,min(tr[po].mid,tarr)),ret);
      if (tarr>tr[po].mid)
      ret=max(segmax(tr[po].rc,max(tr[po].mid+1,tarl),tarr),ret);
      return(ret);
  }
 
  LL quemax(int x,int y){
      LL ret=-1e9;
      while (top[x]!=top[y]){
        if (dep[top[x]]<dep[top[y]]) swap(x,y);
        ret=max(segmax(root[top[x]],id[top[x]],id[x]),ret);
        x=fa[top[x]];
    }
    if (dep[x]<dep[y]) swap(x,y);
    ret=max(segmax(root[top[x]],id[y],id[x]),ret);
    return(ret);
  }
  
  int main(){
      scanf("%d",&n);
      for (int i=1;i<=n;i++) nd[i]=-1;
      
      cnt=0;
      for (int i=1;i<n;i++){
        scanf("%d%d",&t1,&t2);
      addedge(t1,t2);addedge(t2,t1);    
    }
    for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    
    cnt=0;
    dep[1]=1;
    dfs1(1);
    dfs2(1,1);
    
    cnt=0;
    for (int i=1;i<=n;i++)
      if (top[ori[i]]!=top[ori[i+1]])
        root[top[ori[i]]]=cnt+1,
        build(id[top[ori[i]]],i);
    
    int q;
    scanf("%d",&q);
    while (q--){
      scanf("%s%d%d",&st,&t1,&t2);
      if (st[1]=='H')
          edi(root[top[t1]],id[t1],t2);
      if (st[1]=='M')
        printf("%lld\n",quemax(t1,t2));
      if (st[1]=='S')
        printf("%lld\n",quesum(t1,t2));
    }
  }

 

posted @ 2017-11-21 20:56  z1j1n1  阅读(213)  评论(0编辑  收藏  举报