[虚树][树状数组][lca] Jzoj P5908 开荒
Description
尊者神高达作为一个萌新,在升级路上死亡无数次后被一只大黄叽带回了师门。他加入师门后发现有无穷无尽的师兄弟姐妹,这几天新副本开了,尊者神高达的师门作为一个 pve师门,于是他们决定组织一起去开荒。
题目描述:
师门可以看做以 1 为根的一棵树,师门中的每一个人都有一定的装备分数。一共会有 q 个事件。每个事件可能是一次开荒,也可能是因为开荒出了好装备而导致一个人的装分出现了变化。对于一次开荒,会有 k 个人组织,由于师门的号召力很强,所以所有在组织者中任意两个人简单路径上的人都会参加。
Input
接下来 1 行 n 个数,代表每个人的分值;
接下来 n-1 行 u,v 代表一条边
接下来 q 行
Q 代表询问,接下来 k 个数代表组织的人数,读入为 0时停止读入。
C 代表修改,输入 x,w 代表将 x 的分值变为 w
Output
Sample Input
4 4 10 5 2 2 1 2 2 3 2 4 Q 3 4 0 C 3 200 Q 3 4 0 Q 1 4 0
Sample Output
9 207 17样例解释: 第一次询问,参加的人有 2,3,4 5+2+2=9 第一次修改,权值为 10 5 200 2 第二次询问,参加的人有 2,3,4 5+200+2=207 第三次询问,参加的人有 1,2,4 10+5+2=17
Data Constraint
20%的数据 n<=10000,q<=500;
另外 20%的数据 k=2
另外 20%的数据 没有修改操作
所有数据 n,q<=100000,所有询问 k 的和<=1000000
保证数据合法
题解
- 题目大意,有q次操作,询问操作是求k个点两两到lca所经过点的点权和,修改操作就是修改一个点的点权
- 首先,求距离可以用树状数组按照dfs序加入,类似差分约束一样求
- 当然修改也可以
- 那么现在问题就是直接暴力两两lca做显然不行,要找一种更快的做法
- 可以建一棵虚树
- 然后对于虚树上的非父亲节点,直接求出他到父亲的点权和(不包括父亲),而对于父亲则直接加上自己的点权即可
代码
1 #include <cstdio> 2 #include <iostream> 3 #include <algorithm> 4 #include <cstring> 5 using namespace std; 6 const int N=2e5+10; 7 int n,Q,tot,num,cnt,p,w,head[N],v[N],be[N],en[N],fa[N],d[N],dep[N],f[N][20],k[N],q[N]; 8 long long sz[N],ans; 9 struct edge {int to,from;}e[N]; 10 void dfs(int x,int pre) 11 { 12 f[x][0]=fa[x]=pre,be[x]=++tot,d[x]=d[fa[x]]+1,dep[x]=dep[pre]+1; 13 for (int i=head[x];i;i=e[i].from) if (e[i].to!=pre) dfs(e[i].to,x); 14 en[x]=tot; 15 } 16 bool cmp(int x,int y) { return be[x]<be[y]; } 17 int getlca(int x,int y) 18 { 19 if (dep[x]<dep[y]) swap(x,y); 20 for (int i=18;i>=0;i--) if (dep[f[x][i]]>=dep[y]) x=f[x][i]; 21 if (x==y) return x; 22 for (int i=18;i>=0;i--) if (f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i]; 23 return f[x][0]; 24 } 25 void add(int x,int y) { for (;x<=n;x+=x&-x) sz[x]+=y; } 26 long long getsum(int x) 27 { 28 long long v=0; 29 for (;x;x-=x&-x) v+=sz[x]; 30 return v; 31 } 32 void insert(int x,int y) { e[++cnt].to=y; e[cnt].from=head[x]; head[x]=cnt; } 33 int main() 34 { 35 //freopen("kaihuang.in","r",stdin),freopen("kaihuang.out","w",stdout); 36 scanf("%d%d",&n,&Q); 37 for (int i=1;i<=n;i++) scanf("%d",&v[i]); 38 for (int i=1,x,y;i<n;i++) scanf("%d%d",&x,&y),insert(x,y),insert(y,x); 39 dfs(1,0); 40 for (int j=1;j<=19;j++) for (int i=1;i<=n;i++) f[i][j]=f[f[i][j-1]][j-1]; 41 for (int i=1;i<=n;i++) add(be[i],v[i]),add(en[i]+1,-v[i]); 42 while (Q--) 43 { 44 scanf("\n"); 45 char ch=getchar(); int x,y; 46 if (ch=='C') 47 { 48 scanf("%d%d",&x,&y),y-=v[x],v[x]+=y; 49 add(be[x],y),add(en[x]+1,-y); 50 } 51 else 52 { 53 num=1,p=0; scanf("%d",&k[num]); while (k[num]!=0) scanf("%d",&k[++num]); num--; 54 sort(k+1,k+num+1,cmp); 55 w=num; for (int i=1;i<=w-1;i++) k[++num]=getlca(k[i],k[i+1]); 56 sort(k+1,k+num+1,cmp),num=unique(k+1,k+num+1)-k-1; 57 ans=0; 58 for (int i=1;i<=num;i++) 59 { 60 for (;p&&en[q[p]]<be[k[i]];) p--; 61 ans+=p?getsum(be[k[i]])-getsum(be[q[p]]):v[k[i]]; 62 q[++p]=k[i]; 63 } 64 printf("%lld\n",ans); 65 } 66 } 67 }
转载于:https://www.cnblogs.com/Comfortable/p/9802591.html
[虚树][树状数组][lca] Jzoj P5908 开荒相关推荐
- jzoj4050-寻宝游戏【二分,树状数组,LCA】
正题 题目链接:https://jzoj.net/senior/#contest/show/3017/1 题目大意 nnn个点的一棵树,mmm次操作,修改一个地方的宝藏. 每次操作后求拿完所以宝藏并回 ...
- 【BZOJ2819】Nim 树状数组+LCA
[BZOJ2819]Nim Description 著名游戏设计师vfleaking,最近迷上了Nim.普通的Nim游戏为:两个人进行游戏,N堆石子,每回合可以取其中某一堆的任意多个,可以取完,但不可 ...
- 牛客多校1 - Infinite Tree(虚树+换根dp+树状数组)
题目链接:点击查看 题目大意:给出一个无穷个节点的树,对于每个大于 1 的点 i 来说,可以向点 i / minvid[ i ] 连边,这里的 mindiv[ x ] 表示的是 x 的最小质因数,现在 ...
- 【HDU - 6203】ping ping ping(lca+贪心思想,对lca排序,树状数组差分)
题干: 给出一个n+1个点的树,以及p个点对,需要断开一些点,使得这p个点对路径不连通.输出应该断开的最少点数. 解题报告: 从那p个点对入手的话:首先考虑只有一对点的话,肯定是这条路径上的随便一个点 ...
- 「模拟赛20180306」回忆树 memory LCA+KMP+AC自动机+树状数组
题目描述 回忆树是一棵树,树边上有小写字母. 一次回忆是这样的:你想起过往,触及心底--唔,不对,我们要说题目. 这题中我们认为回忆是这样的:给定 \(2\) 个点 \(u,v\) (\(u\) 可能 ...
- Codeforces Gym 101142 G Gangsters in Central City (lca+dfs序+树状数组+set)
题意: 树的根节点为水源,编号为 1 .给定编号为 2, 3, 4, -, n 的点的父节点.已知只有叶子节点都是房子. 有 q 个操作,每个操作可以是下列两者之一: + v ,表示编号为 v 的房子 ...
- Housewife Wind POJ - 2763 倍增LCA+树状数组 或 树链剖分+线段树
题目 链接:http://poj.org/problem?id=2763 Language:Default Housewife Wind Time Limit: 4000MS Memory Lim ...
- HDU 6203 ping ping ping (在线倍增lca+DFS序+树状数组)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6203 #include<bits/stdc++.h> using namespace st ...
- HDU 6203 2017沈阳网络赛 LCA,DFS+树状数组
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6203 题意:n+1 个点 n 条边的树(点标号 0 ~ n),有若干个点无法通行,导致 p 组 U V ...
最新文章
- 9、Kubernetes控制器Controller详解
- 机器学习算法加强——数据清洗
- YOLOv3 《YOLOv3: An Incremental Improvement》论文笔记
- C++, C#, Java, VB.NET,到底该选择哪一门语言?
- C# 页面调用控制台应用程序
- jzoj3501-消息传递【换根法,树形dp】
- ZOJ.3551.Bloodsucker(期望DP)
- python将excel表按地方拆分_Python将一个Excel拆分为多个Excel
- 2020年中国互联网租车报告
- android学习笔记---36_Activity生命周期
- echarts中x轴文件消失_实测实例:labview中波形图X轴刻度任意刻度设置
- 小芭比linux怎么装win7_小户型再怎么装也是小?看完我闭嘴了
- python管道_python 多进程之管道实例(模板)
- 23. jQuery 遍历 - 过滤
- NGN学习笔记6——NGN的业务提供技术
- compositionAPI
- HTTPS的原理与具体实现过程及HTTP服务的虚拟目录简介
- html 图片查看 ie7,兼容ie6跟ie7 的16进制码流在html中显示为图片代码(base64)
- 今天起,上海用户可以用滴滴App免费打无人车了
- python实现淘宝毫秒级秒杀 自动付款
热门文章
- 英语采访问题之:你每天上班的动机是什么?
- 如何在AWS亚马逊云上运行Angular应用
- 太阳能计算机屏幕是什么材质,魅蓝E的屏幕怎么样?屏幕材质是什么?
- java中活锁和死锁的区别_死锁、活锁、饿死和阻塞的个人理解
- vue计算多列和_解决vue 表格table列求和的问题
- 同一目录下有大量文件会影响效率吗_到底是什么原因才导致 select * 效率低下的?
- 除留余数法构造哈希表_哈希表算法原理
- matlab 双音多频 接收端检测到的号码,信号语音论文,关于基于MATLAB的双音多频信号识别相关参考文献资料-免费论文范文...
- linux使用ntp时间同步
- linux进程管理fork,Linux -- 进程管理之 fork() 函数