hdu 5029树链剖分

/*
解:标记区间端点,按深度标记上+下-。
然后用线段树维护求出最小的,再将它映射回来
*/
#pragma comment(linker, "/STACK:102400000,102400000")
#include<stdio.h>
#include<string.h>
#include<vector>
#include<iostream>
#include<algorithm>
using namespace std;
#define N  100500
struct node {
int u,v,next;
}bian[N*2];
int f[N],top[N],fp[N],siz[N],son[N],fa[N],head[N],yong;
int deep[N],cnt;
vector<int>add[N],stra[N];
void init() {
yong=0;cnt=0;
memset(head,-1,sizeof(head));
memset(son,-1,sizeof(son));
}
void addedge(int u,int v) {
 bian[yong].u=u;
 bian[yong].v=v;
 bian[yong].next=head[u];
 head[u]=yong++;
}
void dfs1(int u,int father,int d) {
  deep[u]=d;
  fa[u]=father;
  siz[u]=1;
  int i;
  for(i=head[u];i!=-1;i=bian[i].next) {
    int v=bian[i].v;
    if(v!=father) {
        dfs1(v,u,d+1);
       siz[u]+=siz[v];
       if(son[u]==-1||siz[son[u]]<siz[v])
        son[u]=v;
    }
  }
  return ;
}
void dfs2(int u,int tp) {
   f[u]=++cnt;
   fp[f[u]]=u;
   top[u]=tp;
   if(son[u]==-1)return ;
     dfs2(son[u],tp);
     int i;
     for(i=head[u];i!=-1;i=bian[i].next) {
        int v=bian[i].v;
        if(v!=son[u]&&v!=fa[u])//u写成v了
            dfs2(v,v);
     }
     return ;
}
void update(int u,int v,int w) {
    int f1=top[u];
   int f2=top[v];
   while(f1!=f2) {
       if(deep[f1]<deep[f2]) {
            swap(f1,f2);swap(u,v);
        }
    add[f[f1]].push_back(w);
    stra[f[u]].push_back(w);
    u=fa[f1];
    f1=top[u];
    }
   if(deep[u]>deep[v])
   swap(u,v);
   add[f[u]].push_back(w);
  stra[f[v]].push_back(w);
   return ;
}
struct nodee{
int l,r,node,num;
}tree[N*4];
void pushdown(int t) {
  if(tree[t*2].num>=tree[t*2+1].num) {
    tree[t].num=tree[t*2].num;
    tree[t].node=tree[t*2].node;
  }
  else {
    tree[t].num=tree[t*2+1].num;
    tree[t].node=tree[t*2+1].node;
  }
  return ;
}
void build(int t,int l,int r) {
   tree[t].l=l;
   tree[t].r=r;
   if(l==r){
       // printf("%d\n",l);
    tree[t].node=l;
    tree[t].num=0;
    return ;
   }
   int mid=(l+r)/2;
   build(t*2,l,mid);
   build(t*2+1,mid+1,r);
   pushdown(t);
   return ;
}
void qury(int t,int k,int nu) {
   if(tree[t].l==tree[t].r) {
    tree[t].num+=nu;
   // printf("")
    return ;
   }
   int mid=(tree[t].l+tree[t].r)/2;
   if(k<=mid)
    qury(t*2,k,nu);
   else
    qury(t*2+1,k,nu);
   pushdown(t);
  // printf("%d %d %d\n",tree[t].l,tree[t].r,tree[t].node);
}
int answer[N];
int Max(int v,int vv) {
return v>vv?v:vv;
}
int main() {
   int n,m,i,j,u,v,w,mxx;
   while(scanf("%d%d",&n,&m),n||m) {
    init();
    for(i=1;i<n;i++) {
        scanf("%d%d",&u,&v);
        addedge(u,v);
        addedge(v,u);
    }
    dfs1(1,1,0);
    dfs2(1,1);
  //  printf("f[2]=%d\n",f[2]);
    for(i=1;i<=n;i++)
  add[i].clear(),stra[i].clear();
    mxx=0;
    while(m--) {
        scanf("%d%d%d",&u,&v,&w);
        update(u,v,w);
        mxx=Max(mxx,w);
    }
      build(1,0,mxx);
       for(i=1;i<=n;i++) {
        int len=add[i].size();
     //   printf("%d\n",len);
        for(j=0;j<len;j++) {
       //     printf("%d=%d\n",i,add[i][j]);
            qury(1,add[i][j],1);
        }
        answer[fp[i]]=tree[1].node;
      // printf("%d %d\n",tree[1].node,tree[1].num);
        len=stra[i].size();
           // printf("stralen=%d\n",len);
        for(j=0;j<len;j++) {
      //   printf("st%d=%d\n",i,stra[i][j]);
            qury(1,stra[i][j],-1);
        }
         add[i].clear(),stra[i].clear();
    }
    for(i=1;i<=n;i++)
        printf("%d\n",answer[i]);
   }
return 0;}

转载于:https://www.cnblogs.com/thefirstfeeling/p/4410582.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值