zoukankan      html  css  js  c++  java
  • 点分治

    每次找到去掉后剩下最大联通快最小的点,即重心计算贡献

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
      int next[80001],des[80001],len[80001],nd[40001],cnt,bt[40001],dfstim,size[40001];
      int msiz[40001],b[40001],maxsiz,grav,sta[40001],top,k,fin[40001];
      long long ans;
    
      void addedge(int x,int y,int le){
          next[++cnt]=nd[x];des[cnt]=y;len[cnt]=le;nd[x]=cnt;
      }
      
      void dfs1(int po){
          bt[po]=dfstim;size[po]=1;msiz[po]=0;
          for (int p=nd[po];p!=-1;p=next[p])
            if (b[des[p]]&&bt[des[p]]<dfstim){
                dfs1(des[p]);
                msiz[po]=max(msiz[po],size[des[p]]);
                size[po]+=size[des[p]];
          }  
      }
      
      void dfs2(int po,int tot){
          bt[po]=dfstim;
          if (max(msiz[po],tot-size[po])<maxsiz){
            maxsiz=max(msiz[po],tot-size[po]);
            grav=po;
          }
          for (int p=nd[po];p!=-1;p=next[p])
            if (b[des[p]]&&bt[des[p]]<dfstim)
                dfs2(des[p],tot);
      }
      
      int findgrav(int po){
          dfstim++;dfs1(po);
          maxsiz=1e9;
          dfstim++;dfs2(po,size[po]);
      }
      
      void dfs3(int po,int left){
          if (left>=0) sta[++top]=k-left;
          if (left<0) return;
          bt[po]=dfstim;
          
          for (int p=nd[po];p!=-1;p=next[p])
            if (b[des[p]]&&bt[des[p]]<dfstim)
              dfs3(des[p],left-len[p]);
      }
      
      void work(int po){
          findgrav(po);
          
          b[grav]=0;
          int all=0;
          for (int p=nd[grav];p!=-1;p=next[p])
          if (b[des[p]]){
            dfstim++;top=0;
            dfs3(des[p],k-len[p]);
            ans+=top;
            
            sort(sta+1,sta+top+1);
            int tmp=all;
            for (int i=1;i<=top;i++){
                while (sta[i]+fin[tmp]>k) tmp--;
                ans+=tmp;
            }
            
            for (int i=1;i<=top;i++) fin[++all]=sta[i];
            sort(fin+1,fin+all+1);
          }
          
          for (int p=nd[grav];p!=-1;p=next[p])
            if (b[des[p]]) 
              work(des[p]);
      }
    
      int main(){
          int n;
          scanf("%d",&n);
          for (int i=1;i<=n;i++) nd[i]=-1,b[i]=1;
          for (int i=1;i<n;i++){
            int t1,t2,t3;
          scanf("%d%d%d",&t1,&t2,&t3);
          addedge(t1,t2,t3);addedge(t2,t1,t3);
          }
          scanf("%d",&k);
          
          work(1);
          
          printf("%lld
    ",ans);
      }

     --------------------------------------------------------

    记录下树分治时的结构就可以支持一些修改操作

    CODECHEF DEC17 CHEFFIB

    #pragma GCC optimize(2)
    #include <bits/stdc++.h>
    #define LL long long 
    using namespace std;
       
      const LL mo=1e9+7;
      LL transedA,transedB;
      int bt[400001],dfstim,size[400001],msiz[400001],nd[400001],nxt[800001],des[800001],b[400001];
      int maxsiz,grav,getrot[400001][21],getgrav[400001][21],getdis[400001][21],sta,root1[400001];
      int ndcnt,mxdep[400001],root2[400001][21],cnt;
      LL coef[4000001][2];
      
      void init(){
          coef[0][0]=1;coef[1][1]=1;
          for (int i=2;i<=400000;i++)
            coef[i][0]=(coef[i-1][0]+coef[i-2][0])%mo,
            coef[i][1]=(coef[i-1][1]+coef[i-2][1])%mo;
      }
      
      struct treenode{
          int lc,rc;
          LL A,B,resA,resB;
      }tr[10000001]; 
       
      struct matrix{
        LL a[601][601],tmp[601][601];
        int n,m;
          
        void mul(matrix &b){
          for (int i=0;i<n;i++) 
            for (int j=0;j<b.m;j++) 
              tmp[i][j]=0;
            
          for (int i=0;i<n;i++)
            for (int k=0;k<m;k++)
              if (a[i][k]) 
                for (int j=0;j<b.m;j++)
                  tmp[i][j]+=a[i][k]*b.a[k][j]%mo,tmp[i][j]%=mo;
            
          for (int i=0;i<n;i++)
            for (int j=0;j<b.m;j++)
              a[i][j]=tmp[i][j];
            m=b.m;
          }
      }mata,matb;
      
      void addedge(int x,int y){
          nxt[++cnt]=nd[x];des[cnt]=y;nd[x]=cnt;
      }
      
      void trans(LL A,LL B,int stp){
          /*mata.a[0][0]=A;mata.a[0][1]=B;mata.n=1;mata.m=2;
          matb.a[1][0]=1;matb.a[0][1]=1;matb.a[1][1]=1;matb.a[0][0]=0;matb.n=matb.m=2;
          for (;stp;matb.mul(matb)){
            if (stp&1) mata.mul(matb);
          stp>>=1;    
        }
        transedA=mata.a[0][0];transedB=mata.a[0][1];*/
        transedA=(A*coef[stp][0]%mo+B*coef[stp][1]%mo)%mo;
        transedB=(A*coef[stp+1][0]%mo+B*coef[stp+1][1]%mo)%mo; 
      }
    
      void dfs1(int po){
          bt[po]=dfstim;size[po]=1;msiz[po]=0;
          for (int p=nd[po];p!=-1;p=nxt[p])
            if (b[des[p]]&&bt[des[p]]<dfstim){
                dfs1(des[p]);
                msiz[po]=max(msiz[po],size[des[p]]);
                size[po]+=size[des[p]];
          }  
      }
      
      void dfs2(int po,int tot){
          bt[po]=dfstim;
          if (max(msiz[po],tot-size[po])<maxsiz){
            maxsiz=max(msiz[po],tot-size[po]);
            grav=po;
          }
          for (int p=nd[po];p!=-1;p=nxt[p])
            if (b[des[p]]&&bt[des[p]]<dfstim)
                dfs2(des[p],tot);
      }
      
      int findgrav(int po){
          dfstim++;dfs1(po);
          maxsiz=1e9;
          dfstim++;dfs2(po,size[po]);
      }
      
      int dfs3(int po,int dp,int bel,int ori,int di){
          getrot[po][dp]=bel;
          getgrav[po][dp]=ori;
          getdis[po][dp]=di;
          bt[po]=dfstim;
          
          int ret=1;
          for (int p=nd[po];p!=-1;p=nxt[p])
            if (b[des[p]]&&bt[des[p]]<dfstim)
              ret=max(ret,dfs3(des[p],dp,bel,ori,di+1)+1);
          return(ret);
      }
      
      void work(int po,int dp){
          findgrav(po);
          getgrav[grav][dp]=grav;
          
          if (dp==1) sta=grav;
          
          b[grav]=0;
          root1[grav]=++ndcnt;
          mxdep[grav]=1;
          for (int p=nd[grav];p!=-1;p=nxt[p])
            if (b[des[p]]){
              root2[des[p]][dp]=++ndcnt;
            dfstim++;
            mxdep[grav]=max(mxdep[grav],dfs3(des[p],dp,des[p],grav,1)+1);    
          }
        
        for (int p=nd[grav];p!=-1;p=nxt[p])
          if (b[des[p]])
            work(des[p],dp+1);
      }
    
      void update(int po,int l,int r){
        int mid=(l+r)>>1;
        trans(tr[tr[po].lc].resA,tr[tr[po].lc].resB,r-mid);
        tr[po].resA=transedA+tr[tr[po].rc].resA;tr[po].resA%=mo;
        tr[po].resB=transedB+tr[tr[po].rc].resB;tr[po].resB%=mo;
      }
    
      void edi(int po,int l,int r,int tar,LL A,LL B){
          if (l==r){
            tr[po].A+=A;tr[po].A%=mo;
          tr[po].B+=B;tr[po].B%=mo;
          tr[po].resA=tr[po].A;tr[po].resB=tr[po].B;
          return;    
        }
        
        int mid=(l+r)>>1;
        if (tar<=mid){
          if (!tr[po].lc) tr[po].lc=++ndcnt;
          edi(tr[po].lc,l,mid,tar,A,B);
        }else{
          if (!tr[po].rc) tr[po].rc=++ndcnt;
          edi(tr[po].rc,mid+1,r,tar,A,B);
        }
        update(po,l,r);
      }
    
      void ins(int gra,int po,int k,LL A,LL B,int dp){
          if (gra==po){
            edi(root1[po],1,mxdep[po],1,A,B);
          if (k+2<=mxdep[po])
            trans(A,B,k+1),
            edi(root1[po],1,mxdep[po],k+2,-transedA,-transedB);    
          return;
        }
        
        int left=k-getdis[po][dp];
        if (left>=0){
          trans(A,B,getdis[po][dp]);
          edi(root1[gra],1,mxdep[gra],1,transedA,transedB);
          int rot2=root2[getrot[getgrav[po][dp+1]][dp]][dp];
          trans(A,B,getdis[po][dp]);
          edi(rot2,1,mxdep[gra],1,-transedA,-transedB);
          if (left+2<=mxdep[gra]){
              trans(A,B,k+1); 
            edi(root1[gra],1,mxdep[gra],left+2,-transedA,-transedB);  
            trans(A,B,k+1);
            edi(rot2,1,mxdep[gra],left+2,transedA,transedB);  
          }
            
        }
        ins(getgrav[po][dp+1],po,k,A,B,dp+1);
      }
    
      LL getnum(int po,int l,int r,int tar){
          LL ret=0;
          
          int mid=(l+r)>>1;
          if (tar==r) return(trans(tr[po].resA,tr[po].resB,tar-r),transedA);else
          if (tar<=mid) return(getnum(tr[po].lc,l,mid,tar));else{
            trans(tr[tr[po].lc].resA,tr[tr[po].lc].resB,tar-mid);
          ret=transedA;
          LL tmp=getnum(tr[po].rc,mid+1,r,tar);
          ret+=tmp;
          ret%=mo;
          return(ret);    
        }
      }
    
      LL que(int gra,int po,int dp){
          if (gra==po){
            return(getnum(root1[gra],1,mxdep[gra],1));    
        }
        
        LL ret=getnum(root1[gra],1,mxdep[gra],getdis[po][dp]+1);
        int rot2=root2[getrot[getgrav[po][dp+1]][dp]][dp];
        ret+=getnum(rot2,1,mxdep[gra],getdis[po][dp]+1);
        ret%=mo;
        ret+=que(getgrav[po][dp+1],po,dp+1);
        ret%=mo;
        return(ret);
      }
    
      int main(){
          int T,n,q;
          init();
          
          scanf("%d",&T);
          while (T--){
            scanf("%d%d",&n,&q);cnt=0;
          for (int i=1;i<=ndcnt;i++) tr[i].A=tr[i].B=tr[i].resA=tr[i].resB=tr[i].lc=tr[i].rc=0;    
          ndcnt=0;
          for (int i=1;i<=n;i++) nd[i]=-1,b[i]=1;
          for (int i=1;i<n;i++){
              int t1,t2;
              scanf("%d%d",&t1,&t2);
            addedge(t1,t2);addedge(t2,t1);
          }
          
          work(1,1);
          
          while (q--){
              int opt,t1,t2;
            LL t3,t4;
              scanf("%d",&opt);
              if (opt==1){
                scanf("%d%d%lld%lld",&t1,&t2,&t3,&t4);
                ins(sta,t1,t2,t3,t4,1);
            }else{
              scanf("%d",&t1);
              printf("%lld
    ",(que(sta,t1,1)%mo+mo)%mo);    
            }
          }
        }
      }

     __________________________________________________________

    CODECHEF DEC15 WAYPA

    树上最长回文路径。n<=100000

    树分治时枚举回文串所在的较长的一侧。

      void dfs3(int po,int rt,LL has,LL hasrev,LL powe){
          ha[po]=has;harev[po]=hasrev;
          mptot[has]++;
          mp[rt][has]++;
          bt[po]=dfstim;
          for (int p=nd[po];p!=-1;p=nxt[p])
            if (b[des[p]]&&bt[des[p]]<dfstim){
                fa[des[p]][0]=po;dep[des[p]]=dep[po]+1;
                for (int j=1;j<=20;j++)
                  fa[des[p]][j]=fa[fa[des[p]][j-1]][j-1];
              dfs3(des[p],rt,has*bas+len[p]+1,hasrev+powe*(len[p]+1)*bas,powe*bas);    
          }
      }  
      
      int getfa(int po,int x){
          for (int i=20;i>=0;i--)
            if (x&(1<<i))
              po=fa[po][i];
        return(po);
      }
      
      void dfs4(int po,int rt){
          bt[po]=dfstim;
          if (dep[po]-1>mid) return;
          if (dep[po]-1>=(mid+1)/2){
            int t=getfa(po,mid-(dep[po]-1)),len=mid-(dep[po]-1);
            if (ha[t]==harev[t])
              if (mptot[ha[po]-ha[t]*pow233[len]]-mp[rt][ha[po]-ha[t]*pow233[len]])
              flg=1;    
        }
        for (int p=nd[po];p!=-1;p=nxt[p])
          if (b[des[p]]&&bt[des[p]]<dfstim)
            dfs4(des[p],rt);
      }
  • 相关阅读:
    列表、元组、字典练习
    周总结04
    站立会议07
    人月神话阅读笔记01
    站立会议06
    站立会议05
    站立会议04
    典型用户需求分析第一期
    站立会议03
    站立会议02
  • 原文地址:https://www.cnblogs.com/zhujiangning/p/6219850.html
Copyright © 2011-2022 走看看