[BZOJ 3307]雨天的尾巴
阿新 • • 發佈:2017-10-30
swa 接下來 sample max his ref www. inpu {}
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 877 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\n",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\n",ans[i]); 80 } 81View Code
[BZOJ 3307]雨天的尾巴