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

浙公网安备 33010602011771号