您的位置:首页 > 其它

BZOJ 3307: 雨天的尾巴 线段树合并 树上差分

2017-08-28 15:26 501 查看

3307: 雨天的尾巴

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 610  Solved: 254

[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个点存放最多的物品是哪一种,如果有

多种物品的数量一样,输出编号最小的。如果某个点没有物品

则输出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

对每个节点建权值线段树,树上差分再合并就行了

树上差分就不多说了

这两天发现线段树合并真是个好东西

每个节点的答案递归可以由子树合并而来

听说好像可以链剖? 不会 嘿嘿

#include<cmath>
#include<ctime>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<string>
#include<bitset>
#include<queue>
#include<map>
#include<set>
using namespace std;

inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch<='9'&&ch>='0'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
void print(int x)
{if(x<0)putchar('-'),x=-x;if(x>=10)print(x/10);putchar(x%10+'0');}

const int N=100100;

int n,m,maxn;

int ecnt,last
;
struct EDGE{int to,nt;}e[N<<1];
inline void add(int u,int v)
{e[++ecnt]=(EDGE){v,last[u]};last[u]=ecnt;}

struct changeopt{int u,v,val;friend bool operator <(const changeopt &x,const changeopt &y){return x.val<y.val;}}o
;

int fa
[18],d
,dfn
,pos
,ref
,root
,ans
,cnt;

void dfs(int u)
{
dfn[u]=++cnt;pos[cnt]=u;
for(int i=1;(1<<i)<=d[u];++i)fa[u][i]=fa[fa[u][i-1]][i-1];
for(int i=last[u];i;i=e[i].nt)
{
if(fa[u][0]==e[i].to)continue;
fa[e[i].to][0]=u;d[e[i].to]=d[u]+1;dfs(e[i].to);
}
}

inline int getlca(int u,int v)
{
if(d[u]<d[v])swap(u,v);
int len=d[u]-d[v];
for(int i=0;(1<<i)<=len;++i)if(len&(1<<i))u=fa[u][i];
if(u==v)return u;
for(int i=17;i>=0;--i)if(fa[u][i]^fa[v][i])
u=fa[u][i],v=fa[v][i];
return fa[u][0];
}

struct val_tree{int w,mx,ls,rs;}tr[N<<6];

inline void pushup(int k)
{tr[k].mx=max(tr[tr[k].ls].mx,tr[tr[k].rs].mx);}

inline void modify(int &k,int x,int l,int r,int val,int p)
{
k=++cnt;tr[k].w=tr[x].w+p;
if(l==r){tr[k].mx=tr[k].w;return ;}
int mid=(l+r)>>1;
tr[k].ls=tr[x].ls;tr[k].rs=tr[x].rs;
val<=mid?modify(tr[k].ls,tr[x].ls,l,mid,val,p):modify(tr[k].rs,tr[x].rs,mid+1,r,val,p);
pushup(k);
}

int merge(int x,int y,int l,int r)
{
if(!x)return y;if(!y)return x;
int mid=(l+r)>>1;
tr[x].w=tr[x].w+tr[y].w;
if(l==r){tr[x].mx=tr[x].w;return x;}
tr[x].ls=merge(tr[x].ls,tr[y].ls,l,mid);
tr[x].rs=merge(tr[x].rs,tr[y].rs,mid+1,r);
pushup(x);
return x;
}

int query(int k,int l,int r)
{
if(!tr[k].w)return 0;
if(l==r)return l;
int mid=(l+r)>>1;
if(tr[tr[k].ls].mx==tr[k].mx)return query(tr[k].ls,l,mid);
return query(tr[k].rs,mid+1,r);
}

int main()
{
n=read();m=read();
register int i,u,v,val=0,lca,falca;
for(i=1;i<n;++i){u=read();v=read();add(u,v);add(v,u);}
for(i=1;i<=m;++i){o[i].u=read();o[i].v=read();o[i].val=read();}
dfs(1);
sort(o+1,o+1+m);
maxn=1;ref[1]=o[1].val;
for(i=2;i<=m;++i){if(o[i].val^ref[maxn])maxn++;ref[maxn]=o[i].val;}
for(i=1;i<=m;++i)
{
u=o[i].u;v=o[i].v;if(o[i].val^o[i-1].val)val++;
lca=getlca(u,v);falca=fa[lca][0];
modify(root[u],root[u],1,maxn,val,1);
modify(root[v],root[v],1,maxn,val,1);
modify(root[lca],root[lca],1,maxn,val,-1);
if(falca)modify(root[falca],root[falca],1,maxn,val,-1);
}
for(i=n;i;i--)
{
root[fa[pos[i]][0]]=merge(root[fa[pos[i]][0]],root[pos[i]],1,maxn);
ans[pos[i]]=query(root[pos[i]],1,maxn);
}
for(i=1;i<=n;++i)print(ref[ans[i]]),puts("");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: