zoukankan      html  css  js  c++  java
  • 特技树链剖分

    线段树划分时按照子树的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
    ",quemax(t1,t2));
          if (st[1]=='S')
            printf("%lld
    ",quesum(t1,t2));
        }
      }
  • 相关阅读:
    浅拷贝与深拷贝
    Hibernate入门(1)-第一个Hibernate程序
    Spring入门(10)-Spring JDBC
    【Java,IDEA】创建自己的代码模版快速生成
    【Java,IDEA】使用IDEA自动生成序列化ID
    【Project】原生JavaWeb工程 02 登陆业务的流程(第一阶段样例)
    【AJAX】Asynchronous JavaScript And XML (非同步的JS & XML)
    【JS】06 语法补充
    【JS】05 DOM 文档对象模型 P2 元素的CRUD、Dom集合对象
    【JS】04 DOM 文档对象模型 P1 查找元素、改变内容、绑定事件
  • 原文地址:https://www.cnblogs.com/zhujiangning/p/7875302.html
Copyright © 2011-2022 走看看