zoukankan      html  css  js  c++  java
  • hdu5029 树链剖分 + 线段树

      将树映射在线段上进行操作 然后每个 重链变成一个连续的区间
    #include <iostream>
    #include <cstdio>
    #include <string.h>
    #include <vector>
    #include <algorithm>
    #pragma comment(linker,"/STACk:10240000,10240000")
    using namespace std;
    const int maxn=100005;
    vector<int>F[maxn];
    int son[maxn],num[maxn],fa[maxn],top[maxn],p[maxn],fp[maxn],pos,depth[maxn],ans[maxn];
    vector<int>P[maxn];
    int loc,v;
    struct SegmentItree{
        int num[maxn*4],id[maxn*4];
        void build(int o,int L, int R){
            num[o]=0;
            id[o]=0;
            if(L>=R){
                 num[o]=0; id[o]=L;
                 return ;
            }
            int mid = (L+R)/2;
            build(o*2,L,mid );
            build(o*2+1,mid+1,R);
        }
        void maintain(int o){
             num[o]=0;
             id[o]=0;
             if(num[o*2]==0&&num[o*2+1]==0)return;
             if( num[o*2] >= num[o*2+1] ){
                num[o]=num[o*2];
                id[o]=id[o*2];
             } else{
                num[o] =num[o*2+1];
                id[o]=id[o*2+1];
             }
        }
        void add(int o,int L, int R){
              if(L>=R){
                 num[o]+=v;
                return ;
              }
              int mid = (L+R)>>1;
              if(loc<=mid){
                 add(o*2,L,mid);
              }else{
                 add(o*2+1, mid+1,R);
              }
              maintain(o);
        }
    }T;
    void inti(int n){
       for(int i=0; i<=n+2; ++i)
        F[i].clear(),P[i].clear();
        pos=0;
    }
    void dfs(int cur, int per,int dep){
        depth[cur]=dep;
        son[cur]=-1;
        fa[cur]=per;
        num[cur]=1;
        int Len= F[cur].size();
        for(int i=0; i<Len; ++i){
             int to = F[cur][i];
             if(to==per) continue;
             dfs(to,cur,dep+1); 
             num[cur]+=num[to];
             if( son[ cur ] == -1 || num[ son[cur] ]< num[to] ) son[cur]=to;
        }
    }
    void finde(int cur , int per, int xx){
          top[cur]=xx;
          pos++;
          p[cur]=pos;
          fp[pos]=cur;
          if(son[cur]!=-1)
          finde(son[cur],cur,xx);
          int len = F[cur].size();
          for(int i=0; i<len ;++i ){
               int to= F[cur][i];
               if(to==per||to==son[cur])continue;
               finde(to,cur,to);
          }
    }
    void solve(int x, int y,int d){
        int f1=top[x],f2=top[y];
        while(f1!=f2){
             if(depth[f1]<depth[f2]){
                 int temp = x; x=y; y= temp;
                 temp=f1; f1=f2; f2=temp;
             }
             P[ p[f1] ].push_back(d);
             P[ p[x]+1 ].push_back(-d);
             x=fa[f1];
             f1=top[x];
        }
        if(depth[x]>depth[y]){
            int temp = x; x = y ; y= temp;
        }
        P[p[x]].push_back(d);
        P[p[y]+1].push_back(-d);
    }
    int main()
    {
        int n,m;
        for(;;){
            scanf("%d%d",&n,&m);
            if(n==0&&m==0)break;
            inti(n);
            for(int i=1; i<n ;++i ){
                 int a,b;
                 scanf("%d%d",&a,&b);
                 F[a].push_back(b);
                 F[b].push_back(a);
            }
            dfs(1,0,0);
            finde(1,0,1);
            int N=0;
            for(int i=0; i<m; ++i){
                 int a,b,d;
                 scanf("%d%d%d",&a,&b,&d);
                 solve(a,b,d);
                N=max(d,N);
            }
           memset(ans,0,sizeof(ans));
           if(N!=0){
            T.build(1,1,N);
            for(int i=1; i<=n; ++i){
                 int L = P[i].size();
                 for(int j=0; j<L; ++j){
                     int to= P[i][j];
                     if(to>0){
                         v=1;
                         loc=to;
                     }else{
                         v=-1;
                         loc=-to;
                     }
                     T.add(1,1,N);
                 }
                 if(T.num[1]!=0)
                 ans[fp[i]]=T.id[1];
                 else ans[fp[i]]=0;
            }
           }
            for(int i=1; i<=n; ++i)
                printf("%d
    ",ans[i]);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    ARC 066D Xor Sum AtCoder
    哈尔滨理工大学---沼跃鱼(待整理)
    C#从字符串获取文件路径
    蓝桥杯---机器人行走
    关于float和double的输入输出问题
    湖南多校对抗赛---Jerry's trouble
    湖南多校对抗赛---Good subsequence
    湖南多校对抗赛---Rectangle(01背包)
    蓝桥杯---公式解析
    蓝桥杯---砝码称重
  • 原文地址:https://www.cnblogs.com/Opaser/p/3995401.html
Copyright © 2011-2022 走看看