zoukankan      html  css  js  c++  java
  • 动态树分治

    感受:

    就是把分治结构变成树(并不需要真正建出,只需要记录父亲)

    然后每个点维护子树到该点的信息,和子树到父亲点的信息

    总体来说还是很模板的一个东西

    题目大概分成两类:

    (1)树上黑白点染色,问一个点到所有黑点的距离和

    这种就是原来真正的树结构上信息修改,那么一般就是将修改的点在分治树上所在的链每个点维护的信息加加减减。

    (2)另一种就是询问体现动态,比如距离某个点距离<=k的点的权值和

    这种问题的突破点在于原树的信息是不改变的。所以我们可以在分治树上每个点维护一个vector数组来储存信息(有序)

    分治树本身就是一种均摊的东西,树高为logn,每个点的信息最多出现logn次,所以这样每个点暴力sort均摊也是nlogn的

    这样在处理询问的时候我们就可以二分更新答案了。

    COGS2278 (第一种)

    #include<bits/stdc++.h>
    using namespace std;
    int read(){
      int x=0,f=1;char ch=getchar();
      while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
      while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
      return x*f;
    }
    #define N 200005
    #define ll long long
    int n,m;
    struct Node{
      int to,next,v;
    }e[N<<1];
    int tot,c[N],head[N],p[N][22],dep[N],Log[22];
    int rt,sum,mx[N],sz[N],g[N],pos;
    ll ans,Dis[N],Disf[N],num[N],dis[N];
    bool vis[N];
    void add(int x,int y,int z){
      e[++tot]=(Node){y,head[x],z};head[x]=tot;
      e[++tot]=(Node){x,head[y],z};head[y]=tot;
    }
    /*----------------------prepare--------------------------------*/
    void dfs(int x,int f){
      p[x][0]=f;dep[x]=dep[f]+1;
      for(int i=head[x];i;i=e[i].next)if(e[i].to!=f){
      	dis[e[i].to]=dis[x]+1ll*e[i].v;dfs(e[i].to,x);
      }
    }
    void prepare(){
      for(int j=1;j<=20;j++)
        for(int i=1;i<=n;i++)p[i][j]=p[p[i][j-1]][j-1];
      Log[1]=0;
      for(int i=2;i<=20;i++)Log[i]=Log[i>>1]+1;
    }
    int LCA(int x,int y){
      if(dep[x]<dep[y])swap(x,y);
      for(int i=20;i>=0;i--)if(dep[x]-(1<<i)>=dep[y])x=p[x][i];
      if(x==y)return x;
      for(int i=20;i>=0;i--)
        if(p[x][i]!=p[y][i])x=p[x][i],y=p[y][i];
      return p[x][0];
    }
    ll d(int x,int y){return dis[x]+dis[y]-2*dis[LCA(x,y)];} 
    /*--------------------------动态树-----------------------------*/
    void getroot(int x,int f){
      mx[x]=0;sz[x]=1;
      for(int i=head[x];i;i=e[i].next)if(!vis[e[i].to]&&e[i].to!=f){
        getroot(e[i].to,x);sz[x]+=sz[e[i].to];
        if(sz[e[i].to]>mx[x])mx[x]=sz[e[i].to];
      }
      if(sum-sz[x]>mx[x])mx[x]=sum-sz[x];
      if(mx[x]<mx[rt])rt=x;
    }
    void get_g(int x,int f){
      getroot(x,f);vis[rt]=1;g[rt]=f;int t=rt;
      for(int i=head[rt];i;i=e[i].next)if(!vis[e[i].to]){
        sum=sz[e[i].to];rt=0;get_g(e[i].to,t);
      }
    }
    void white(int x){
      num[x]--;Dis[x]-=d(x,pos);
      if(!g[x])return;
      Disf[x]-=d(g[x],pos);
      white(g[x]);
    }
    void black(int x){
      num[x]++;Dis[x]+=d(x,pos);
      if(!g[x])return;
      Disf[x]+=d(g[x],pos);
      black(g[x]);
    }
    void query(int x){
      ans+=num[x]*d(x,pos)+Dis[x];
      if(!g[x])return;
      ans-=(num[x]*d(g[x],pos)+Disf[x]);
      query(g[x]);
    }
    /*-------------------------------------------------------------*/
    int main(){
      freopen("A_Tree.in","r",stdin);
      freopen("A_Tree.out","w",stdout);
      n=read();m=read();
      for(int i=1;i<n;i++){
      	int x=read(),y=read(),z=read();
      	add(x,y,z);
      }
      
      dfs(1,0);prepare();
      sum=n;rt=0;mx[0]=n;get_g(1,0);
    //  for(int i=1;i<=n;i++)cout<<i<<' '<<g[i]<<endl;
      char s[5];
      while(m--){
      	scanf("%s",s);
      	int x=read();pos=x;
      	if(s[0]=='Q'){
      	  ans=0;query(x);printf("%lld
    ",ans);
      	}
      	else{
      	  if(c[x])white(x);
      	  else black(x);
      	  c[x]^=1;
    	}
      }
      return 0;
    }
    

    COGS 2258. [HZOI 2015]复仇的序幕曲 (第二种)

    #include<bits/stdc++.h>
    using namespace std;
    int read(){
      int x=0,f=1;char ch=getchar();
      while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
      while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
      return x*f;
    }
    #define N 80005
    struct Node{
      int to,next,v;
    }e[N<<1];
    int n,m,a[N];
    int tot,head[N],dep[N],dis[N],p[N][22];
    int sum,ans,pos,rt,mx[N],sz[N],g[N];
    bool vis[N];
    vector<pair<int,int> > Dis[N],Disf[N];
    void add(int x,int y,int z){
      e[++tot]=(Node){y,head[x],z};head[x]=tot;
      e[++tot]=(Node){x,head[y],z};head[y]=tot;
    }
    /**********************************************************/
    void dfs(int x,int f){
      dep[x]=dep[f]+1;p[x][0]=f;
      for(int i=head[x];i;i=e[i].next)if(e[i].to!=f){
        dis[e[i].to]=dis[x]+e[i].v;dfs(e[i].to,x);
      }
    }
    void prepare(){
      for(int j=1;j<=20;j++)
        for(int i=1;i<=n;i++)
          p[i][j]=p[p[i][j-1]][j-1];
    }
    int LCA(int x,int y){
      if(dep[x]<dep[y])swap(x,y);
      for(int i=20;i>=0;i--)if(dep[x]-(1<<i)>=dep[y])x=p[x][i];
      if(x==y)return x;
      for(int i=20;i>=0;i--)
        if(p[x][i]!=p[y][i])
          x=p[x][i],y=p[y][i];
      return p[x][0];
    }
    int d(int x,int y){return dis[x]+dis[y]-2*dis[LCA(x,y)];}
    /**********************************************************/
    void getroot(int x,int f){
      mx[x]=0;sz[x]=1;
      for(int i=head[x];i;i=e[i].next)if(e[i].to!=f&&!vis[e[i].to]){
        getroot(e[i].to,x);sz[x]+=sz[e[i].to];
        if(sz[e[i].to]>mx[x])mx[x]=sz[e[i].to];
      }
      if(sum-sz[x]>mx[x])mx[x]=sum-sz[x];
      if(mx[x]<mx[rt])rt=x;
    }
    void get_g(int x,int f){
      getroot(x,f);g[rt]=f;int t=rt;vis[t]=1;
      for(int i=head[rt];i;i=e[i].next)if(!vis[e[i].to]){
        sum=sz[e[i].to];rt=0;get_g(e[i].to,t);
      }
    }
    #define mp make_pair<int,int>
    #define F first
    #define S second
    void update(int x){
      Dis[x].push_back(mp(d(x,pos),a[pos]));
      Disf[x].push_back(mp(d(g[x],pos),a[pos]));
      if(g[x]>0)update(g[x]);
    }
    int erfen(vector<pair<int,int> > &v,int lim){
      int l=0,r=v.size()-1,mid,tmp=-1;
      while(l<=r){
        mid=l+r>>1;
        if(v[mid].F<=lim)tmp=mid,l=mid+1;
        else r=mid-1;
      }
      if(tmp==-1)return 0;
      return v[tmp].S;
    }
    void query(int x,int lim){
      ans+=erfen(Dis[x],lim-d(pos,x));
      if(!g[x])return;
      ans-=erfen(Disf[x],lim-d(pos,g[x]));
      query(g[x],lim);
    }
    int main(){
      freopen("SS.in","r",stdin);
      freopen("SS.out","w",stdout);
      n=read();m=read();
      for(int i=1;i<=n;i++)a[i]=read();
      for(int i=1;i<n;i++){
        int x=read(),y=read(),z=read();
        add(x,y,z);
      }
      
      dfs(1,0);prepare();
      sum=n;mx[rt=0]=n;get_g(1,0);
      
      for(int i=1;i<=n;i++)pos=i,update(i);
      for(int i=1;i<=n;i++){
        sort(Dis[i].begin(),Dis[i].end());
        sort(Disf[i].begin(),Disf[i].end());
        for(int j=1;j<Dis[i].size();j++){
          Dis[i][j].S+=Dis[i][j-1].S;
          Disf[i][j].S+=Disf[i][j-1].S;
    	}
      }
      
      while(m--){
        int x=read(),y=read();pos=x;ans=0;
        query(x,y);printf("%d
    ",ans);
      }
      return 0;
    }
    

      

    HNOI2015 开店 (第二种)

    还没写QAQ

  • 相关阅读:
    七 、linux正则表达式
    六、通配符
    Codeforces1099D.Sum in the tree(贪心)
    叮,出现!
    Codeforces1056E.Check Transcription(枚举+Hash)
    2018.11.25 AMC-ICPC 亚洲区域赛(焦作站)吊银
    Gym101889J. Jumping frog(合数分解+环形dp预处理)
    Gym101889E. Enigma(bfs+数位)
    Gym101889B. Buggy ICPC(打表)
    Codeforces1076F. Summer Practice Report(贪心+动态规划)
  • 原文地址:https://www.cnblogs.com/wjyi/p/5654616.html
Copyright © 2011-2022 走看看