[JZOJ 5908] [NOIP2018模拟10.16] 开荒(kaihuang)解题报告 (树状数组+思维)
题目链接:
https://jzoj.net/senior/#contest/show/2529/1
题目:
题目背景:
尊者神高达作为一个萌新,在升级路上死亡无数次后被一只大黄叽带回了师门。他加入师门后发现有无穷无尽的师兄弟姐妹,这几天新副本开了,尊者神高达的师门作为一个 pve师门,于是他们决定组织一起去开荒。
题目描述:
师门可以看做以 1 为根的一棵树,师门中的每一个人都有一定的装备分数。一共会有 q 个事件。每个事件可能是一次开荒,也可能是因为开荒出了好装备而导致一个人的装分出现了变化。对于一次开荒,会有 k 个人组织,由于师门的号召力很强,所以所有在组织者中任意两个人简单路径上的人都会参加。
题目大意:
在树上给出多个点,每次询问包含这些点的最小连通块的点权之和,带修改
题解:
对于每一个询问,我们把点按照dfs序从小到大排序。画个图我们发现,假设当前点为第i个点,第i个点的贡献就是从第i个点到与第i-1个点的LCA上的路径上的点权和,但是不包括LCA的点权。为什么不包括LCA的点权呢?发现其实我们从第1个点到最终的LCA上的点权和(这个要算上最终的LCA)都没有计算,最后一起计算就是了
为什么是对的呢?我们考虑到排名靠后的点要么在上一个点的子树里,要么就是新开一个子树。对于前者我们发现公共LCA不上移,直接计算到上一个点的路径和就是了,而事实上上一个点和这个点的LCA就是上一个点。对于后者我们发现公共LCA发生上移,这在最终的答案被我们统计了进去。
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
typedef long long ll; const int N=1e5+;
int n,Q,tot,tim;
int head[N],son[N],dep[N],fa[N][],dfn[N],id[N],sz[N],a[N];
ll val[N],t[N];
struct EDGE
{
int to,nxt;
}edge[N<<];
inline ll read()
{
char ch=getchar();
ll s=,f=;
while (ch<''||ch>'') {if (ch=='-') f=-;ch=getchar();}
while (ch>=''&&ch<='') {s=(s<<)+(s<<)+ch-'';ch=getchar();}
return s*f;
}
void link(int u,int v)
{
edge[++tot]=(EDGE){v,head[u]};
head[u]=tot;
}
void dfs(int x,int pre)
{
sz[x]=;fa[x][]=pre;dfn[x]=++tim;id[tim]=x;
for (int i=;i<;i++) fa[x][i]=fa[fa[x][i-]][i-];
for (int i=head[x];i;i=edge[i].nxt)
{
int y=edge[i].to;
if (y==pre) continue;
dep[y]=dep[x]+;
dfs(y,x);
sz[x]+=sz[y];
}
}
void add(int x,ll y)
{
while (x<=n)
{
t[x]+=y;
x+=x&-x;
}
}
ll sum(int x)
{
ll re=;
while (x)
{
re+=t[x];
x-=x&-x;
}
return re;
}
int lca(int x,int y)
{
if (dep[x]<dep[y]) swap(x,y);
for (int i=;i>=;i--) if (dep[fa[x][i]]>=dep[y]) x=fa[x][i];
if (x==y) return x;
for (int i=;i>=;i--) if (fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
return fa[x][];
}
bool cmp(int a,int b){return dfn[a]<dfn[b];}
int main()
{
freopen("kaihuang.in","r",stdin);
freopen("kaihuang.out","w",stdout);
n=read();Q=read();
for (int i=;i<=n;i++) val[i]=read();
for (int i=,u,v;i<n;i++)
{
u=read();v=read();
link(u,v);link(v,u);
}
dep[]=;dfs(,);
//for (int i=1;i<=n;i++) printf("%d ",sz[i]);
//printf("\n");
for (int i=;i<=n;i++)
{
add(dfn[i],val[i]);add(dfn[i]+sz[i],-val[i]);
}
char op[];
for (int i=;i<=Q;i++)
{
scanf("%s",op);
if (op[]=='C')
{
int x=read();ll y=read();
add(dfn[x],-val[x]);add(dfn[x]+sz[x],val[x]);
val[x]=y;
add(dfn[x],y);add(dfn[x]+sz[x],-y);
}
if (op[]=='Q')
{
int k=;
while ()
{
int x=read();
if (!x) break;
a[++k]=x;
}
sort(a+,a++k,cmp);
if (k==)
{
printf("%lld\n",val[a[]]);
continue;
}
ll re=sum(dfn[a[]]);int LCA=a[];
for (int i=;i<=k;i++)
{
LCA=lca(LCA,a[i]);
re+=sum(dfn[a[i]]);
re-=sum(dfn[lca(a[i],a[i-])]);
}
re-=sum(dfn[fa[LCA][]]);
printf("%lld\n",re);
}
}
return ;
}
[JZOJ 5908] [NOIP2018模拟10.16] 开荒(kaihuang)解题报告 (树状数组+思维)的更多相关文章
- [jzoj 5930] [NOIP2018模拟10.26】山花 解题报告 (质因数分类)
题目链接: http://172.16.0.132/senior/#contest/show/2538/2 题目: 小S决定从某一个节点$u$开始对其子树中与$u$距离小于$K$的节点代表的花树进行采 ...
- [JZOJ 5893] [NOIP2018模拟10.4] 括号序列 解题报告 (Hash+栈+map)
题目链接: https://jzoj.net/senior/#main/show/5893 题目: 题解: 考虑暴力怎么做,我们枚举左端点,维护一个栈,依次加入元素,与栈顶元素和栈内第二个元素相同时弹 ...
- [JZOJ 5905] [NOIP2018模拟10.15] 黑暗之魂(darksoul) 解题报告 (拓扑排序+单调队列+无向图基环树)
题目链接: http://172.16.0.132/senior/#main/show/5905 题目: oi_juruo热爱一款名叫黑暗之魂的游戏.在这个游戏中玩家要操纵一名有 点生命值的无火的余灰 ...
- [JZOJ 5885] [NOIP2018模拟9.27] 物理实验 解题报告 (思维)
题目链接: https://jzoj.net/senior/#main/show/5885 题目: 题解: 把$a$数组按升序排序 我们可以枚举$x$,发现对于任意$x$,最优情况下$y$一定等于$x ...
- [JZOJ 5909] [NOIP2018模拟10.16] 跑商(paoshang) 解题报告 (圆方树)
题目链接: https://jzoj.net/senior/#contest/show/2529/2 题目: 题目背景:尊者神高达很穷,所以他需要跑商来赚钱题目描述:基三的地图可以看做 n 个城市,m ...
- [JZOJ 5888] [NOIP2018模拟9.29] GCD生成树 解题报告 (最大生成树+公约数)
题目链接: http://172.16.0.132/senior/#main/show/5888 题目: 题解: 思路是这样的:两个数的最大公约数一定不会比这两个数的任意一个数大.因此我们把权值相等的 ...
- [jzoj 5926] [NOIP2018模拟10.25] naive 的图 解题报告(kruskal重构树+二维数点)
题目链接: https://jzoj.net/senior/#main/show/5926 题目: 题解: 显然最小的最大路径在最小生成树上(最小生成树=最小瓶颈生成树) 于是我们建出kruskal重 ...
- 【洛谷】NOIP提高组模拟赛Day2【动态开节点/树状数组】【双头链表模拟】
U41571 Agent2 题目背景 炎炎夏日还没有过去,Agent们没有一个想出去外面搞事情的.每当ENLIGHTENED总部组织活动时,人人都说有空,结果到了活动日,却一个接着一个咕咕咕了.只有不 ...
- 「模拟赛20180307」三元组 exclaim 枚举+树状数组
题目描述 给定 \(n,k\) ,求有多少个三元组 \((a,b,c)\) 满足 \(1≤a≤b≤c≤n\)且\(a + b^2 ≡ c^3\ (mod\ k)\). 输入 多组数据,第一行数据组数\ ...
随机推荐
- keras中使用预训练模型进行图片分类
keras中含有多个网络的预训练模型,可以很方便的拿来进行使用. 安装及使用主要参考官方教程:https://keras.io/zh/applications/ https://keras-cn. ...
- redis windows安装与使用
是什么 Redis(Remote Dictionary Server)远程字典服务器 开源免费 C语言编写的 key/value分布式内存数据库,基于内存运行 Redis支持数据的持久化,可以将内存中 ...
- hadoop配置历史服务器
此文档不建议当教程,仅供参考 配置历史服务器 我是在hadoop1机器上配置的 配置mapred-site.xml <property> <name>mapreduce.job ...
- Java 系列之spring学习--springmvc注解参数传递(六)
一.绑定参数注解如下 @RequestParam 绑定单个请求数据,既可以是URL中的参数,也可以是表单提交的参数或上传的文件. 它有三个属性: value 用于设置参数名. defa ...
- 分布式memcache
使用多台memchache服务器,形成memchache集群.目的是为了提升memchache所能使用的硬件资源数量.多台memcached服务器之间不相互通讯.分布式算法由客户端实现,(php来说, ...
- surface 更新提示
- 阿里云Maven中央仓库配置
方式一:统一配置 在maven安装目录/conf下的settings.xml 文件里配置mirrors的子节点,添加如下mirror <mirror> <id>alimaven ...
- Safari new Date() 兼容问题
我的时间 var myTime = "2015-12-31 12:10:21"; 正常写法 var newTime = new Date(myTime); safari兼容写法 ...
- [Reading] Asking while Reading
Asking while Reading ——读Java垃圾收集器与内存分配策略 Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的“高墙”,墙外面的人想进去,墙里面的人却想出来. 为什么 ...
- 页面加载通过javascript来修改控件属性
function changeFormElementStatus(tagNames) { var tagNameArr = tagNames.split("," ...