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 MBSubmit: 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
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