[luogu4556]雨天的尾巴

[luogu4556]雨天的尾巴

luogu
发现是一顿子修改然后再询问,那么把修改树上差分一下再线段树合并
但是...
如果你只有35分...
https://www.luogu.org/discuss/show/88259

#include<bits/stdc++.h>
using namespace std;
const int _=1e5+5;
int re(){
    int x=0,w=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    return x*w;
}
int n,m,cnt,N=1e5,tot;
int h[_],f[_],a[_],b[_],z[_],fa[_],lca[_],rt[_],ans[_];
int mx[_*67],id[_*67],ls[_*67],rs[_*67];
bool vis[_];
vector<int>p[_];
struct edge{int to,next;}e[_<<1];
void link(int u,int v){
    e[++cnt]=(edge){v,h[u]};h[u]=cnt;
    e[++cnt]=(edge){u,h[v]};h[v]=cnt;
}
int find(int x){return x==f[x]?x:f[x]=find(f[x]);}
void dfs(int u){
    for(int i=h[u];i;i=e[i].next){
        int v=e[i].to;
        if(v==fa[u])continue;
        fa[v]=u;dfs(v);f[v]=u;
    }
    vis[u]=1;
    for(int i=0,j=p[u].size();i<j;i++){
        int k=p[u][i],v=a[k]==u?b[k]:a[k];
        if(vis[v])lca[k]=find(v);
    }
}
void pu(int x){
    mx[x]=max(mx[ls[x]],mx[rs[x]]);
    if(mx[ls[x]]==mx[rs[x]])id[x]=min(id[ls[x]],id[rs[x]]);
    else id[x]=mx[ls[x]]>mx[rs[x]]?id[ls[x]]:id[rs[x]];
}
void upd(int&x,int l,int r,int k,int v){
    if(!x)x=++tot;
    if(l==r){mx[x]+=v;id[x]=l;return;}
    int mid=(l+r)>>1;
    if(k<=mid)upd(ls[x],l,mid,k,v);
    else upd(rs[x],mid+1,r,k,v);pu(x);
}
int merge(int a,int b,int l,int r){
    if(!a||!b)return a|b;
    if(l==r)mx[a]+=mx[b];
    else{
        int mid=(l+r)>>1;
        ls[a]=merge(ls[a],ls[b],l,mid);
        rs[a]=merge(rs[a],rs[b],mid+1,r);
        pu(a);
    }return a;
}
void solve(int u){
    for(int i=h[u];i;i=e[i].next){
        int v=e[i].to;
        if(v==fa[u])continue;
        solve(v);
        rt[u]=merge(rt[u],rt[v],1,N);
    }
    ans[u]=id[rt[u]];
}
int main(){
    n=re();m=re();
    for(int i=1;i<=n;i++)f[i]=i;
    for(int i=1,u,v;i<n;i++){
        u=re(),v=re();link(u,v);
    }
    for(int i=1;i<=m;i++){
        a[i]=re(),b[i]=re();z[i]=re();
        p[a[i]].push_back(i);
        p[b[i]].push_back(i);
    }
    dfs(1);
    for(int i=1;i<=m;i++){
        upd(rt[a[i]],1,N,z[i],1);
        upd(rt[b[i]],1,N,z[i],1);
        upd(rt[lca[i]],1,N,z[i],-1);
        upd(rt[fa[lca[i]]],1,N,z[i],-1);
    }
    solve(1);
    for(int i=1;i<=n;i++)printf("%d\n",ans[i]);
    return 0;
}

原文地址:https://www.cnblogs.com/sdzwyq/p/10100318.html

时间: 2024-08-02 04:58:41

[luogu4556]雨天的尾巴的相关文章

luogu4556 雨天的尾巴 (线段树合并+差分)

题目背景 深绘里一直很讨厌雨天.灼热的天气穿透了前半个夏天,后来一场大雨和随之而来的洪水,浇灭了一切.虽然深绘里家乡的小村落对洪水有着顽固的抵抗力,但也倒了几座老房子,几棵老树被连根拔起,以及田地里的粮食被弄得一片狼藉.无奈的深绘里和村民们只好等待救济粮来维生.不过救济粮的发放方式很特别.题目描述 首先村落里的一共有n座房屋,并形成一个树状结构.然后救济粮分m次发放,每次选择两个房屋(x,y),然后对于x到y的路径上(含x和y)每座房子里发放一袋z类型的救济粮.然后深绘里想知道,当所有的救济粮发

Luogu4556 雨天的尾巴 树上差分、线段树合并

传送门 一个套路题-- 树上差分+线段树合并即可 注意一个细节:$pushup$的时候如果最大值为$0$一定要把最大值对应的答案也设为$0$,否则会$WA$第二个点 另外如果这道题空限变小了请不要交这份代码,因为这份代码没有卡空间... 1 #include<bits/stdc++.h> 2 #define mid ((l + r) >> 1) 3 //This code is written by Itst 4 using namespace std; 5 6 inline in

bzoj3307: 雨天的尾巴

3307: 雨天的尾巴 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 479  Solved: 214[Submit][Status][Discuss] Description N个点,形成一个树状结构.有M次发放,每次选择两个点x,y对于x到y的路径上(含x,y)每个点发一袋Z类型的物品.完成所有发放后,每个点存放最多的是哪种物品. Input 第一行数字N,M接下来N-1行,每行两个数字a,b,表示a与b间有一条边再接下来M行,每行三个数字x

GDOI模拟雨天的尾巴【树套树】

雨天的尾巴 深绘里一直很讨厌雨天.灼热的天气穿透了前半个夏天,后来一场大雨和随之而来的洪水,浇灭了一切.虽然深绘里家乡的小村落对洪水有着顽固的抵抗力,但也倒了几座老房子,几棵老树被连根拔起,以及田地里的粮食被弄得一片狼藉.无奈的深绘里和村民们只好等待救济粮来维生.不过救济粮的发放方式很特别.首先村落里的一共有n 座房屋,并形成一个树状结构.然后救济粮分m 次发放,每次选择两个房屋(x,y),然后对于x 到y 的路径上(含x 和y) 每座房子里发放一袋z 类型的救济粮.然后深绘里想知道,当所有的救

[bzoj3307]雨天的尾巴_线段树合并

雨天的尾巴 bzoj-3307 题目大意:N个点,形成一个树状结构.有M次发放,每次选择两个点x,y对于x到y的路径上(含x,y)每个点发一袋Z类型的物品.完成所有发放后,每个点存放最多的是哪种物品. 想法:我们像主席树一样,维护桶然后对应节点合并即可. 最后,附上丑陋的代码... ... #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #define

P4556 [Vani有约会]雨天的尾巴 树链剖分 线段树合并

P4556 [Vani有约会]雨天的尾巴 提交2.75k 通过789 时间限制1.00s 内存限制125.00MB 提交代码加入收藏 题目提供者yyy2015c01 难度省选/NOI- 历史分数100 提交记录查看题解 标签 查看算法标签 相关讨论 进入讨论版 查看讨论 推荐题目 查看推荐 展开 题目背景 深绘里一直很讨厌雨天.灼热的天气穿透了前半个夏天,后来一场大雨和随之而来的洪水,浇灭了一切.虽然深绘里家乡的小村落对洪水有着顽固的抵抗力,但也倒了几座老房子,几棵老树被连根拔起,以及田地里的粮

[树上差分][线段树合并]JZOJ 3397 雨天的尾巴

Description 深绘里一直很讨厌雨天. 灼热的天气穿透了前半个夏天,后来一场大雨和随之而来的洪水,浇灭了一切. 虽然深绘里家乡的小村落对洪水有着顽固的抵抗力,但也倒了几座老房子,几棵老树被连 根拔起,以及田地里的粮食被弄得一片狼藉. 无奈的深绘里和村民们只好等待救济粮来维生. 不过救济粮的发放方式很特别. 首先村落里的一共有n 座房屋,并形成一个树状结构.然后救济粮分m 次发放,每次选择 两个房屋(x,y),然后对于x 到y 的路径上(含x 和y) 每座房子里发放一袋z 类型的救济粮.

BZOJ 3307 雨天的尾巴 线段树

题目大意:给定一棵树,有m个操作,每次给一条路径上的每个点分发一个颜色为z的物品,所有操作结束后输出每个点上数量最多的是哪种物品 对于每个操作,我们在x和y上各打上一个插入z的标记,然后在LCA(x,y)和Fa(LCA(x,y))上各打上一个删除z的标记 然后我们对z维护线段树 DFS一遍,对于每个节点进行如下操作: 1.将所有子节点的线段树合并过来 2.处理标记,该插♂入的插♂入,该删除的删除 3.查询最大值作为答案 这样的复杂度是O(mlogm)的 然而跑不过树链剖分什么鬼--是我没离散化的

bzoj 3307 雨天的尾巴

题目链接:传送门 题目大意:中文题,略 题目思路:网上有题解说是合并线段树的,但是太难蒟蒻不会,只能用树剖求解 如果不是树而是一维数组我们会怎么解? 当然是利用前缀和思想标记 (L) v+1,(R+1) v-1,然后扫一遍 用线段树取最大复杂度 nlogn 现在是搬到了树上,怎么做? 利用树链剖分拆成链然后在像一维那样做就行,复杂度n(logn)^2 1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib&g