3307: 雨天的尾巴
Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 709 Solved: 296
[Submit][Status][Discuss]Description
N个点,形成一个树状结构。有M次发放,每次选择两个点x,y对于x到y的路径上(含x,y)每个点发一袋Z类型的物品。完成所有发放后,每个点存放最多的是哪种物品。
Input
第一行数字N,M
接下来N-1行,每行两个数字a,b,表示a与b间有一条边
再接下来M行,每行三个数字x,y,z.如题Output
输出有N行
每i行的数字表示第i个点存放最多的物品是哪一种,如果有
多种物品的数量一样,输出编号最小的。如果某个点没有物品
则输出0Sample Input
20 50
8 6
10 6
18 6
20 10
7 20
2 18
19 8
1 6
14 20
16 10
13 19
3 14
17 18
11 19
4 11
15 14
5 18
9 10
12 15
11 14 87
12 1 87
14 3 84
17 2 36
6 5 93
17 6 87
10 14 93
5 16 78
6 15 93
15 5 16
11 8 50
17 19 50
5 4 87
15 20 78
1 17 50
20 13 87
7 15 22
16 11 94
19 8 87
18 3 93
13 13 87
2 1 87
2 6 22
5 20 84
10 12 93
18 12 87
16 10 93
8 17 93
14 7 36
7 4 22
5 9 87
13 10 16
20 11 50
9 16 84
10 17 16
19 6 87
12 2 36
20 9 94
9 2 84
14 1 94
5 5 94
8 17 16
12 8 36
20 17 78
12 18 50
16 8 94
2 19 36
10 18 36
14 19 50
4 12 50
Sample Output
87
36
84
22
87
87
22
50
84
87
50
36
87
93
36
94
16
87
50
50
1<=N,M<=100000
1<=a,b,x,y<=N
1<=z<=10^9
解题报告
线段树启发式暴力合并
首先我们肯定会想到简单的树剖套线段树套权值线段树的做法,但显然,假如数据卡你的话,是可以随便卡掉的,$MLE$+$RE$
所以我们不能在大范围的区间进行权值线段树的开点与修改,于是我们考虑差分
我们在树上的每一个节点开一棵权值线段树,动态开点保证空间,然后在树上差分,路径两端点对应加1,$LCA$与$LCA$父节点对应减1,就可以达到差分的效果了,最后$dfs$合并线段树统计答案即可
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 inline int read(){ 6 int sum(0);char ch(getchar()); 7 for(;ch<'0'||ch>'9';ch=getchar()); 8 for(;ch>='0'&&ch<='9';sum=sum*10+(ch^48),ch=getchar()); 9 return sum; 10 } 11 const int mxv(1e9); 12 struct edge{int e;edge *n;}*pre[100005]; 13 inline void insert(int s,int e){edge *tmp(new edge);tmp->e=e;tmp->n=pre[s];pre[s]=tmp;} 14 int n,m,fa[100005][20],dep[100005]; 15 inline void dfs(int u){ 16 for(int i=1;(1<<i)<=dep[u];++i)fa[u][i]=fa[fa[u][i-1]][i-1]; 17 for(edge *i=pre[u];i;i=i->n){ 18 int e(i->e);if(e==fa[u][0])continue; 19 fa[e][0]=u;dep[e]=dep[u]+1;dfs(e); 20 } 21 } 22 inline int lca(int x,int y){ 23 if(dep[x]<dep[y])swap(x,y); 24 int delta(dep[x]-dep[y]); 25 for(int i=0;delta;++i)if(delta&(1<<i))delta^=1<<i,x=fa[x][i]; 26 if(x==y)return x; 27 for(int i=19;i>=0;--i)if(fa[x][i]^fa[y][i])x=fa[x][i],y=fa[y][i];return fa[x][0]; 28 } 29 #define get_mx(x) (x?x->mx:0) 30 #define get_pos(x) (x?x->pos:0) 31 struct node{ 32 node *lch,*rch; 33 int mx; 34 node():lch(NULL),rch(NULL),mx(0){} 35 inline void pushup(){this->mx=max(get_mx(this->lch),get_mx(this->rch));} 36 }*root[100005]; 37 inline void update(node *&x,int pos,int w,int l,int r){ 38 if(!x){x=new node();} 39 if(l==r){x->mx+=w;/*cout<<' '<<l<<' '<<r<<endl;*/return;} 40 int mid((l+r)>>1); 41 if(pos<=mid)update(x->lch,pos,w,l,mid); 42 else update(x->rch,pos,w,mid+1,r);x->pushup(); 43 } 44 int ans[100005]; 45 inline void merge(node *&x,node *&y,int l,int r){ 46 if(!y)return;if(!x){x=y;return;} 47 if(l==r){x->mx+=y->mx;return;} 48 int mid((l+r)>>1); 49 merge(x->lch,y->lch,l,mid);merge(x->rch,y->rch,mid+1,r); 50 x->pushup(); 51 } 52 inline int query(node *x,int ll,int rr,int l,int r){ 53 if(!x)return 0;if(ll<=l&&r<=rr)return x->mx;int mid((l+r)>>1),ret(0); 54 if(ll<=mid)ret=query(x->lch,ll,rr,l,mid);if(mid<rr)ret=max(ret,query(x->rch,ll,rr,mid+1,r));return ret; 55 } 56 inline int query_pos(node *x,int l,int r,int mx){ 57 if(!x)return 0;if(l==r)return l;int mid((l+r)>>1);//cout<<l<<' '<<r<<' '<<mx<<' '<<get_mx(x->lch)<<endl; 58 if(get_mx(x->lch)==mx)return query_pos(x->lch,l,mid,mx); 59 return query_pos(x->rch,mid+1,r,mx); 60 } 61 /*inline void print(node *x){ 62 if(!x)return; 63 printf("%d %d %d %d ",x->l,x->r,x->mx,x->pos); 64 print(x->lch);print(x->rch); 65 }*/ 66 inline void cal(int u){ 67 for(edge *i=pre[u];i;i=i->n){ 68 int e(i->e);if(e==fa[u][0])continue; 69 cal(e);merge(root[u],root[e],1,mxv);//cout<<"print "<<u<<endl;print(root[u]); 70 } 71 ans[u]=query(root[u],1,mxv,1,mxv);/*cout<<ans[u]<<' ';*/ans[u]=query_pos(root[u],1,mxv,ans[u]);//cout<<ans[u]<<endl; 72 } 73 int main(){ 74 n=read(),m=read();for(int i=1;i<n;++i){int x(read()),y(read());insert(x,y);insert(y,x);}dfs(1); 75 while(m--){ 76 int x(read()),y(read()),z(read()),tp(lca(x,y)); 77 update(root[x],z,1,1,mxv);update(root[y],z,1,1,mxv);update(root[tp],z,-1,1,mxv);update(root[fa[tp][0]],z,-1,1,mxv); 78 } 79 cal(1);for(int i=1;i<=n;++i)printf("%d ",ans[i]); 80 } 81