BZOJ3307: 雨天的尾巴

中文题意简单易懂 不再叙述

题解: 很明显我们考虑到运用树上差分的思想 加入这个元素等于在u,v位置加入 删除等于在lca(u,v)和fa[lca(u,v)]的地方-1 这样问题就转化成 从叶子节点dfs将这些点操作 并查询区间num最大且vul最小的值即可 这样我们可以通过线段树维护 然后本题的一个难点就是线段树合并了吧 讲道理 以前的合并的题都是启发式合并 但是这个题有个性质就是你用线段树维护 那么你就只需要将都有的节点从小到上更新 没有的之间连上去即可 然后就做完了  复杂度均摊下来应该是nlogn 空间复杂度同理也是nlogn

#include <bits/stdc++.h>
#define pii pair<int,int>
const int MAXN=1e5+10;
#define ll long long
using namespace std;
int n,m;
vector<int>vec[MAXN];
ll read(){
    ll x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
    return x*f;
}
int fa[MAXN],num[MAXN],dep[MAXN],son[MAXN];
void dfs1(int v,int pre,int deep){
    num[v]=1;fa[v]=pre;dep[v]=deep+1;
    for(int i=0;i<vec[v].size();i++){
	if(vec[v][i]!=pre){
	    dfs1(vec[v][i],v,deep+1);
	    num[v]+=num[vec[v][i]];
	    if(son[v]==-1||num[son[v]]<num[vec[v][i]])son[v]=vec[v][i];
	}
    }
}
int p[MAXN],fp[MAXN],cnt,tp[MAXN],sz;
void dfs2(int v,int td){
    p[v]=++cnt;fp[p[v]]=v;tp[v]=td;
    if(son[v]!=-1)dfs2(son[v],td);
    for(int i=0;i<vec[v].size();i++){
	if(vec[v][i]!=son[v]&&vec[v][i]!=fa[v])dfs2(vec[v][i],vec[v][i]);
    }
}
int Lca(int u,int v){
    int uu=tp[u];int vv=tp[v];
    while(uu!=vv){
	if(dep[uu]<dep[vv])swap(uu,vv),swap(u,v);
	u=fa[uu];uu=tp[u];
    }
    if(dep[u]>dep[v])swap(u,v);
    return u;
}
typedef struct que{
    int u,v,c,lca;
}que;
que q[MAXN];
vector<int>v1;
vector<pii>v2[MAXN];
typedef struct node{
    int num,maxx,l,r;
}node;
node d[MAXN*16*4];int ans[MAXN],rt[MAXN];
void up(int x){
    if(!d[x].l&&!d[x].r)return ;
    d[x].num=0;
    if(d[x].l){d[x].num=d[d[x].l].num;d[x].maxx=d[d[x].l].maxx;}
    if(d[x].r){
	if(!d[x].num)d[x].num=d[d[x].r].num,d[x].maxx=d[d[x].r].maxx;
	else {
	    if(d[x].num<d[d[x].r].num)d[x].num=d[d[x].r].num,d[x].maxx=d[d[x].r].maxx;
	    else if(d[x].num==d[d[x].r].num)d[x].maxx=min(d[x].maxx,d[d[x].r].maxx);
	}
    }
}
int cnt1;
void update(int &rt,int l,int r,int t,int vul){
    if(!rt)rt=++cnt1;   
    if(l==r){d[rt].num+=vul;d[rt].maxx=l;return ;}
    int mid=(l+r)>>1;
    if(t<=mid)update(d[rt].l,l,mid,t,vul);
    else update(d[rt].r,mid+1,r,t,vul);
    up(rt);
}
void merge(int &x,int y,int l,int r){
    if(!x&&!y)return ;
    if(x&&y){
	if(l==r){
	    d[x].num+=d[y].num;return ;
	}
	int mid=(l+r)>>1;
	merge(d[x].l,d[y].l,l,mid);
	merge(d[x].r,d[y].r,mid+1,r);
    }
    else{
	if(y)x=y;
	return ;
    }
    up(x);
}
void dfs(int v){
    for(int i=0;i<vec[v].size();i++){
	if(vec[v][i]!=fa[v]){
	    dfs(vec[v][i]);
	    merge(rt[v],rt[vec[v][i]],1,sz);
	}
    }
    for(int i=0;i<v2[v].size();i++){
	update(rt[v],1,sz,v2[v][i].first,v2[v][i].second);}
   // cout<<d[rt[v]].num<<"====:::"<<" "<<v<<endl;
   // for(int i=0;i<v2[v].size();i++)cout<<v2[v][i].first<<" "<<v2[v][i].second<<endl;
    if(!d[rt[v]].num)ans[v]=0;
    else ans[v]=d[rt[v]].maxx;
}
int main(){
    n=read();m=read();
    for(int i=1;i<=n;i++)son[i]=-1;
    int u,v;
    for(int i=1;i<n;i++)u=read(),v=read(),vec[u].push_back(v),vec[v].push_back(u);
    dfs1(1,0,0);dfs2(1,1);
    for(int i=1;i<=m;i++)q[i].u=read(),q[i].v=read(),q[i].c=read(),v1.push_back(q[i].c),q[i].lca=Lca(q[i].u,q[i].v);
    //for(int i=1;i<=m;i++)cout<<q[i].lca<<" ";
    //cout<<endl;
    sort(v1.begin(),v1.end());
    sz=unique(v1.begin(),v1.end())-v1.begin();
 //   built(1,1,sz);
    for(int i=1;i<=m;i++){
	q[i].c=lower_bound(v1.begin(),v1.begin()+sz,q[i].c)-v1.begin()+1,v2[q[i].u].push_back(make_pair(q[i].c,1));
	v2[q[i].v].push_back(make_pair(q[i].c,1));v2[q[i].lca].push_back(make_pair(q[i].c,-1));
	v2[fa[q[i].lca]].push_back(make_pair(q[i].c,-1));
    }
    dfs(1);
    for(int i=1;i<=n;i++){
	if(!ans[i])puts("0");
	else printf("%d\n",v1[ans[i]-1]);
    }
    return 0;
}

 

3307: 雨天的尾巴

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 1004  Solved: 400
[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

posted @ 2018-06-05 19:13  wang9897  阅读(129)  评论(0编辑  收藏  举报