【BZOJ 3307】 3307: 雨天的尾巴 (线段树+树链剖分)

3307: 雨天的尾巴

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 458  Solved: 210

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个点存放最多的物品是哪一种,如果有
多种物品的数量一样,输出编号最小的。如果某个点没有物品
则输出0

Sample 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

HINT

Source

 

 

【分析】

  什么时候样例这样良心。。

  按照z排序,然后树剖标记一下区间,然后统计个数相同的区间add到线段树里面求min,这些区间个数不会超过3*mlogn,因为树剖区间logn个,一个新的区间最多只会把原来的分割成3部分。

 

  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<cstring>
  4 #include<iostream>
  5 #include<algorithm>
  6 using namespace std;
  7 #define Maxn 100010
  8 
  9 int mymax(int x,int y) {return x>y?x:y;}
 10 
 11 struct node
 12 {
 13     int l,r,lc,rc,mx,id;
 14     int lazy,lad;
 15 }tr[Maxn*2];
 16 
 17 struct nnode{int x,y,z;}t[Maxn],tt[Maxn],t3[Maxn*40];
 18 int first[Maxn],len;
 19 
 20 bool cmp(nnode x,nnode y) {return x.z<y.z;}
 21 bool cmp2(nnode x,nnode y) {return x.x<y.x;}
 22 
 23 void ins(int x,int y)
 24 {
 25     t[++len].x=x;t[len].y=y;
 26     t[len].z=first[x];first[x]=len;
 27 }
 28 
 29 int fa[Maxn],son[Maxn],tp[Maxn],sm[Maxn],dep[Maxn];
 30 void dfs1(int x,int ff)
 31 {
 32     dep[x]=dep[ff]+1;
 33     fa[x]=ff;sm[x]=1;son[x]=0;
 34     for(int i=first[x];i;i=t[i].z) if(t[i].y!=ff)
 35     {
 36         int y=t[i].y;
 37         dfs1(y,x);
 38         sm[x]+=sm[y];
 39         if(son[x]==0||sm[y]>sm[son[x]]) son[x]=y;
 40     }
 41 }
 42 
 43 int cnt,dfn[Maxn];
 44 void dfs2(int x,int tpp)
 45 {
 46     dfn[x]=++cnt;tp[x]=tpp;
 47     if(son[x]) dfs2(son[x],tpp);
 48     for(int i=first[x];i;i=t[i].z) if(t[i].y!=fa[x]&&t[i].y!=son[x])
 49     {
 50         int y=t[i].y;
 51         dfs2(y,y);
 52     }
 53 }
 54 
 55 int tot=0;
 56 int build(int l,int r)
 57 {
 58     int x=++tot;
 59     tr[x].l=l;tr[x].r=r;tr[x].mx=0;tr[x].lazy=0;
 60     if(l!=r)
 61     {
 62         int mid=(l+r)>>1;
 63         tr[x].lc=build(l,mid);
 64         tr[x].rc=build(mid+1,r);
 65     }
 66     else tr[x].lc=tr[x].rc=0;
 67     return x;
 68 }
 69 
 70 void upd(int x)
 71 {
 72     if(tr[x].lazy==0) return;
 73     int lc=tr[x].lc,rc=tr[x].rc;
 74     if(tr[x].lazy>tr[x].mx) tr[x].mx=tr[x].lazy,tr[x].id=tr[x].lad;
 75     if(tr[x].l==tr[x].r) {tr[x].lazy=0;return;}
 76     if(tr[x].lazy>tr[lc].lazy) tr[lc].lazy=tr[x].lazy,tr[lc].lad=tr[x].lad;
 77     if(tr[x].lazy>tr[rc].lazy) tr[rc].lazy=tr[x].lazy,tr[rc].lad=tr[x].lad;
 78     tr[x].lazy=0;
 79 }
 80 
 81 void change(int x,int l,int r,int y,int id)
 82 {
 83     if(tr[x].l==l&&tr[x].r==r)
 84     {
 85         if(y>tr[x].lazy) tr[x].lazy=y,tr[x].lad=id;
 86         upd(x);return;
 87     }
 88     upd(x);
 89     int mid=(tr[x].l+tr[x].r)>>1;
 90     if(r<=mid) change(tr[x].lc,l,r,y,id);
 91     else if(l>mid) change(tr[x].rc,l,r,y,id);
 92     else {change(tr[x].lc,l,mid,y,id);change(tr[x].rc,mid+1,r,y,id);}
 93     if(tr[tr[x].lc].mx>=tr[tr[x].rc].mx) tr[x].mx=tr[tr[x].lc].mx,tr[x].id=tr[tr[x].lc].id;
 94     else tr[x].mx=tr[tr[x].rc].mx,tr[x].id=tr[tr[x].rc].id;
 95 }
 96 
 97 int query(int x,int y)
 98 {
 99     upd(x);
100     if(tr[x].l==tr[x].r) return tr[x].id;
101     int mid=(tr[x].l+tr[x].r)>>1;
102     if(y<=mid) return query(tr[x].lc,y);
103     return query(tr[x].rc,y);
104 }
105 
106 int tl;
107 int add(int x,int y)
108 {
109     while(tp[x]!=tp[y])
110     {
111         if(dep[tp[x]]<dep[tp[y]]) swap(x,y);
112         t3[++tl].x=dfn[tp[x]];t3[tl].y=1;
113         t3[++tl].x=dfn[x]+1;t3[tl].y=-1;
114         x=fa[tp[x]];
115     }
116     if(dep[x]>dep[y]) swap(x,y);
117     t3[++tl].x=dfn[x];t3[tl].y=1;
118     t3[++tl].x=dfn[y]+1;t3[tl].y=-1;
119 }
120 
121 void ffind(int st,int ed,int id)
122 {
123     tl=0;
124     for(int i=st;i<=ed;i++) 
125     {
126         add(tt[i].x,tt[i].y);
127     }
128     sort(t3+1,t3+1+tl,cmp2);
129     int nw=0;
130     for(int i=1;i<tl;i++)
131     {
132         nw+=t3[i].y;
133         if(t3[i].x!=t3[i+1].x&&nw!=0)
134         {
135             // printf("%d %d %d\n",t3[i].x,t3[i+1].x-1,nw);
136             change(1,t3[i].x,t3[i+1].x-1,nw,id);
137         }
138     }
139 }
140 
141 int main()
142 {
143     int n,m;
144     scanf("%d%d",&n,&m);
145     len=0;
146     memset(first,0,sizeof(first));
147     for(int i=1;i<n;i++)
148     {
149         int x,y;
150         scanf("%d%d",&x,&y);
151         ins(x,y);ins(y,x);
152     }
153     dep[0]=0;dfs1(1,0);
154     cnt=0;dfs2(1,1);
155     for(int i=1;i<=m;i++) scanf("%d%d%d",&tt[i].x,&tt[i].y,&tt[i].z);
156     sort(tt+1,tt+1+m,cmp);
157     build(1,n);
158     int st=1;
159     for(int i=1;i<=m;i++)
160     {
161         if(i==m||tt[i].z!=tt[i+1].z)
162         {
163             ffind(st,i,tt[i].z);
164             st=i+1;
165         }
166     }
167     for(int i=1;i<=n;i++) printf("%d\n",query(1,dfn[i]));
168     return 0;
169 }
View Code

 

好像Po姐有更好的方法?

 

2017-03-27 16:10:51

posted @ 2017-03-27 16:11  konjak魔芋  阅读(210)  评论(0编辑  收藏  举报