hdu 5029 Relief grain
给一颗树,给q次询问,每次询问给一条路径x到y并且给这条路染色v。
问最后每个点分别被哪种颜色染色的最多。
首先考虑在直线上的这种问题,我们可以把每次染色的区间左端点和右端点记录下来。然后建一颗颜色的权值线段树。
每次到左端点的时候把权值线段树的颜色++,到右端点+1的时候把颜色--。类似差分。然后查找整个线段树的最大值。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <cstdio> #include <queue> #include <cstring> #include <iostream> #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 #define up rt,rt<<1,rt<<1|1 #define mem(x) memset(x,0,sizeof(x)) #define mem1(x) memset(x,-1,sizeof(x)) using namespace std; const int M = 1e5+7; int n,_,pos; int cnt,tot,head[M]; int sz[M],dep[M],f[M],son[M],rnk[M],top[M],id[M]; int ans[M]; vector<int> vecl[M],vecr[M]; struct edge { int v,next; }e[M<<1]; void init(){ cnt=tot=0;mem1(head); } void add(int u,int v){ e[++cnt].v=v;e[cnt].next=head[u]; head[u]=cnt; } /*******************find son********************/ void dfs(int u,int fa,int d){ sz[u]=1,son[u]=-1,f[u]=fa,dep[u]=d; for(int i=head[u];~i;i=e[i].next){ int v=e[i].v; if(v==fa) continue; dfs(v,u,d+1); sz[u]+=sz[v]; if(son[u]==-1||sz[v]>sz[son[u]]) son[u]=v; } return ; } void dfs1(int u,int t){ id[u]=++tot; rnk[tot]=u; top[u]=t; if(son[u]==-1) return ; dfs1(son[u],t); for(int i=head[u];~i;i=e[i].next){ int v=e[i].v; if(v==f[u]||v==son[u]) continue; dfs1(v,v); } return ; } /*********************剖分*********************/ void sum(int x,int y,int col){//把路径化为直线上的区间更新 int fx=top[x],fy=top[y]; while(fx!=fy){ if(dep[fx]>dep[fy]){ vecl[id[fx]].push_back(col); vecr[id[x]+1].push_back(col); x=f[fx],fx=top[x]; } else{ vecl[id[fy]].push_back(col); vecr[id[y]+1].push_back(col); y=f[fy],fy=top[y]; } } if(dep[x]<dep[y]) { vecl[id[x]].push_back(col); vecr[id[y]+1].push_back(col); } else{ vecl[id[y]].push_back(col); vecr[id[x]+1].push_back(col); } } /****************segment_tree******************/ struct Tree { int mx,val; }tree[M<<2]; void Pushup(int rt,int l,int r){ if(tree[r].mx>tree[l].mx){ tree[rt].mx=tree[r].mx;tree[rt].val=tree[r].val; } else if(tree[l].mx>=tree[r].mx){ tree[rt].mx=tree[l].mx;tree[rt].val=tree[l].val; } } void build(int l,int r,int rt){ tree[rt].mx=0; //cout<<rt<<" "<<l<<" "<<r<<endl; if(l==r){ tree[rt].val=l; return ; } int mid=(l+r)>>1; build(lson); build(rson); Pushup(up); } void update(int l,int r,int rt,int v){ if(l==r){ tree[rt].mx+=v; return ; } int mid=(l+r)>>1; if(pos<=mid) update(lson,v); else update(rson,v); Pushup(up); } /************************solve**************************/ void solve(){ build(1,100000,1); for(int i=1;i<=n;i++){ for(int j=0;j<vecl[i].size();j++){//左区间+ pos=vecl[i][j]; update(1,100000,1,1); } for(int j=0;j<vecr[i].size();j++){//右区间- pos=vecr[i][j]; update(1,100000,1,-1); } ans[rnk[i]]=(tree[1].mx==0?0:tree[1].val); } for(int i=1;i<=n;i++) printf("%d\n",ans[i]); } int main(){ while(~scanf("%d%d",&n,&_)){ if(n==0&&_==0) break; init(); for(int i=1;i<n;i++){ vecl[i].clear();vecr[i].clear(); int from,to; scanf("%d%d",&from,&to); add(from,to);add(to,from); } vecl[n].clear();vecr[n].clear(); dfs(1,-1,1);dfs1(1,1); while(_--){ int from,to,col; scanf("%d%d%d",&from,&to,&col); sum(from,to,col); } if(_==0){ for(int i=1;i<=n;i++) printf("0\n"); continue; } solve(); } return 0; }