bzoj 3307 雨天的尾巴

题目链接:传送门

题目大意:中文题,略

题目思路:网上有题解说是合并线段树的,但是太难蒟蒻不会,只能用树剖求解

     如果不是树而是一维数组我们会怎么解?

     当然是利用前缀和思想标记 (L) v+1,(R+1) v-1,然后扫一遍

     用线段树取最大复杂度 nlogn

     现在是搬到了树上,怎么做?

     利用树链剖分拆成链然后在像一维那样做就行,复杂度n(logn)^2

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstdlib>
  4 #include <cmath>
  5 #include <algorithm>
  6 #include <cstring>
  7 #include <stack>
  8 #include <cctype>
  9 #include <queue>
 10 #include <string>
 11 #include <vector>
 12 #include <set>
 13 #include <map>
 14 #include <climits>
 15 #define lson rt<<1,l,mid
 16 #define rson rt<<1|1,mid+1,r
 17 #define fi first
 18 #define se second
 19 #define ping(x,y) ((x-y)*(x-y))
 20 #define mst(x,y) memset(x,y,sizeof(x))
 21 #define mcp(x,y) memcpy(x,y,sizeof(y))
 22 using namespace std;
 23 #define gamma 0.5772156649015328606065120
 24 #define MOD 1000000007
 25 #define inf 0x3f3f3f3f
 26 #define N 100005
 27 #define maxn 30010
 28 typedef pair<int,int> PII;
 29 typedef long long LL;
 30 LL read(){
 31     LL x=0,f=1;char ch=getchar();
 32     while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
 33     while(ch>=‘0‘&&ch<=‘9‘){x=(x<<3)+(x<<1)+ch-‘0‘;ch=getchar();}
 34     return x*f;
 35 }
 36 vector<int>V[N];
 37 map<int,int>M;
 38 int num[N],ncnt,head[N],hcnt,ans[N];
 39 int n,m,k,L,R,sz,v;
 40 int son[N],siz[N],id[N],tid;
 41 int top[N],dep[N],fa[N],posi[N];
 42 struct Node{int to,nxt,v;}node[N<<3];
 43 struct Seg{int v,va;}seg[N<<2];
 44 inline void add(int x,int y,int v){
 45     node[hcnt].to=y,node[hcnt].nxt=head[x],node[hcnt].v=v,head[x]=hcnt++;
 46 }
 47 void dfs1(int u,int f,int deep){
 48     fa[u]=f,++siz[u],dep[u]=deep;
 49     for(int e:V[u]){
 50         if(e==f)continue;
 51         dfs1(e,u,deep+1);siz[u]+=siz[e];
 52         if(!son[u]||siz[son[u]]<siz[e])son[u]=e;
 53     }
 54 }
 55 void dfs2(int u,int tp){
 56     id[u]=++tid,posi[tid]=u,top[u]=tp;
 57     if(!son[u])return; dfs2(son[u],tp);
 58     for(int e:V[u])if(!id[e])dfs2(e,e);
 59 }
 60 void pushup(int rt){
 61     if(seg[rt<<1].v>seg[rt<<1|1].v)seg[rt]=seg[rt<<1];
 62     else if(seg[rt<<1].v<seg[rt<<1|1].v)seg[rt]=seg[rt<<1|1];
 63     else if(num[seg[rt<<1].va]<num[seg[rt<<1|1].va])seg[rt]=seg[rt<<1];
 64     else seg[rt]=seg[rt<<1|1];
 65 }
 66 void update(int rt,int l,int r){
 67     if(l==r){seg[rt].v+=v;seg[rt].va=l;return;}
 68     int mid=l+r>>1;
 69     if(L<=mid)update(lson);
 70     else update(rson);
 71     pushup(rt);
 72 }
 73 void build(int rt,int l,int r){
 74     if(l==r){seg[rt].va=l;return;}
 75     int mid=l+r>>1;
 76     build(lson);build(rson);
 77 }
 78 int main(){
 79     int i,j,group,x,y,Case=0;
 80     n=read(),m=read();
 81     mst(head,-1);
 82     for(i=1;i<n;++i){
 83         x=read(),y=read();
 84         V[x].push_back(y);
 85         V[y].push_back(x);
 86     }
 87     dfs1(1,1,1);dfs2(1,1);
 88     for(i=1;i<=m;++i){
 89         x=read(),y=read();v=read();
 90         if(!M[v]){
 91             M[v]=++ncnt;
 92             num[ncnt]=v;
 93         }
 94         v=M[v];
 95         while(top[x]!=top[y]){
 96             if(dep[top[x]]<dep[top[y]])swap(x,y);
 97             L=id[top[x]],R=id[x];
 98             add(L,v,1);add(R+1,v,-1);
 99             x=fa[top[x]];
100         }
101         if(dep[x]<dep[y])swap(x,y);
102         L=id[y],R=id[x];
103         add(L,v,1);add(R+1,v,-1);
104     }
105     build(1,1,m);
106     for(i=1;i<=n;++i){
107         for(j=head[i];~j;j=node[j].nxt){
108             L=node[j].to;v=node[j].v;
109             update(1,1,m);
110         }
111         ans[posi[i]]=num[seg[1].va];
112     }
113     for(i=1;i<=n;++i)printf("%d\n",ans[i]);
114     return 0;
115 }
时间: 2024-12-15 15:38:11

bzoj 3307 雨天的尾巴的相关文章

BZOJ 3307 雨天的尾巴 线段树

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

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

[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

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

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

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

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

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

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

[Vani有约会]雨天的尾巴

我之前考试是遇到过这题,但是数据范围k<=20,状压就能过. 结果原题范围k<=100000-- 果断线段树合并. 普及线段树合并: 比如两个相同大小的线段树,将b树各个区间上的值合并到a树上,从树根开始合并,然后递归合并左右儿子,有三种情况: (假设现在a树遍历到x点,b树遍历到y点) 1.x,y至少其一未被修改过(语文不好勿喷),则将x变为遍历过的那个. 2.x,y位于叶节点(l==r),则sum[x]+=sum[y]. 3.一般情况,递归处理左右儿子,最后更新当前点. 本题中合并如下: