当前位置:网站首页>[ACM-ICPC 2018 沈阳赛区网络预赛] J.Ka Chang (分块+dfs序)
[ACM-ICPC 2018 沈阳赛区网络预赛] J.Ka Chang (分块+dfs序)
2022-04-23 06:21:00 【Zimba_】
题意:
给定一棵 n n n个点的树,有两种操作:
1. 1. 1.给所有深度为 L L L的点权值加上 X X X。
2. 2. 2.查询根为 X X X的子树的点权和。
给出 q q q次操作,对于每次操作 2 2 2,输出结果。
( 1 ≤ n , q ≤ 1 0 5 ) (1\leq n,q \leq 10^{5}) (1≤n,q≤105)
思路:
如果只有操作 1 1 1,我们可以维护 b f s bfs bfs序,这样同深度的点一定在一段连续的区间中。
如果只有操作 2 2 2,我们可以维护 d f s dfs dfs序,这样某个点的子树一定在一段连续的区间中。
但是二者不可兼得,我们只能保留其一。
对于这题操作 2 2 2,我们仍维护一个 d f s dfs dfs序,就变成区间求和了。
现在主要的问题是解决操作 1 1 1。
我们可以发现,同一深度点的点权一定是相同的。 所以要得到某个子树的权值和,我们只要知道这个子树每个深度的点的个数即可。但是我们计算的时候,不能遍历所有深度,我们也没法对于每个点预处理它的子树所有的深度点的个数。然后就有了后面的做法。
我们把所有的点按深度归类,同一个深度的放在一起。
考虑按归类后的集合大小分块。
当某个深度的集合大小 ≤ n \leq \sqrt{n} ≤n时,那么我们要更新该深度的时候,直接暴力遍历 + + +单点修改即可,复杂度为 o ( n n l o g n ) o(n\sqrt{n}logn) o(nnlogn)。
当某个深度的集合大小 ≥ n \geq \sqrt{n} ≥n时,这样的集合数量肯定少于 n \sqrt{n} n,我们可以对于每个点,
预处理出这不到 n \sqrt{n} n个集合中在子树里的大小,然后查询的时候,暴力遍历这些深度,直接得到个数来计算。
这样,总的复杂度就是 o ( n n l o g n ) o(n\sqrt{n}logn) o(nnlogn)。
代码
ps:题中的深度是从 0 0 0开始的。。。
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const ll mod=1000000007;
const int N = 100001;
ll c[100005];
void add(int x,ll k) {
while(x<=N) {
c[x]+=k;
x+=x&-x;
}
}
ll getSum(int x) {
ll res=0;
while(x>0) {
res+=c[x];
x-=x&-x;
} return res;
}
int n,B;
vector<int>v[100005];
vector<int>st[100005];
ll dval[100005];
int dep[100005],id[100005],idx,ed[100005],edd;
void dfs(int x,int pre)
{
id[x]=++idx;
edd=x;
dep[x]=dep[pre]+1;
for(int i=0;i<v[x].size();i++)
{
int to=v[x][i];
if(to!=pre)
{
dfs(to,x);
}
}
ed[x]=edd;
}
vector<int>dv[100005],g;
void dfs2(int x,int pre)
{
for(int i=0;i<v[x].size();i++)
{
int to=v[x][i];
if(to!=pre)
{
dfs2(to,x);
for(int j=0;j<g.size();j++)dv[x][j]+=dv[to][j];
}
}
for(int j=0;j<g.size();j++)if(g[j]==dep[x])dv[x][j]++;
}
int main()
{
int q;
scanf("%d%d",&n,&q);
B=sqrt(n);
for(int i=1;i<n;i++)
{
int a,b;
scanf("%d%d",&a,&b);
v[a].push_back(b);
v[b].push_back(a);
}
dfs(1,0);
for(int i=1;i<=n;i++)st[dep[i]].push_back(i);
for(int i=1;i<=n;i++)if(st[i].size()>B)g.push_back(i);
for(int i=1;i<=n;i++)
{
for(int j=0;j<g.size();j++)dv[i].push_back(0);
}
dfs2(1,0);
while(q--)
{
int opt;
scanf("%d",&opt);
if(opt==1)
{
int d,x;
scanf("%d%d",&d,&x);
d++;
if(st[d].size()<=B)
{
for(auto t:st[d])add(id[t],x);
}
else
{
dval[d]+=x;
}
}
else
{
int x;
scanf("%d",&x);
ll ans=getSum(id[ed[x]])-getSum(id[x]-1);
for(int j=0;j<g.size();j++)ans+=dv[x][j]*dval[g[j]];
printf("%lld\n",ans);
}
}
return 0;
}
版权声明
本文为[Zimba_]所创,转载请带上原文链接,感谢
https://blog.csdn.net/weixin_43785386/article/details/108640193
边栏推荐
- 记录一个查询兼容性的网站,String.replaceAll()兼容性报错
- 浅谈BFC(块格式化上下文)
- PyTorch 13. Nested functions and closures (dog head)
- PyTorch 12. Hook usage
- golang实现一个带Web界面的五险一金计算器
- Urban emergency management - urban emergency communication command and dispatching system
- Swin transformer to onnx
- 记录阿里云服务器挖矿程序处理
- el-select 中v-model绑定值,数据回显只显示value,不显示label
- The difference between null and undefined
猜你喜欢
el-table 横向滚动条固定在可视窗口底部
Metro wireless intercom system
海南凤凰机场智能通信解决方案
Meishe technology launches professional video editing solution for desktop -- Meiying PC version
记录一些npm 有关的问题(杂乱记录)
学习资料
Intelligent communication solution of Hainan Phoenix Airport
免费开源农业物联网云平台(Version:3.0.1)
How does the public and Private Integrated walkie talkie realize cooperative work under multi-mode communication?
可视化常见问题解决方案(九)背景颜色问题
随机推荐
按需引入vant组件
安装tui-editor失败,快速解决方案
可视化常见问题解决方案(八)数学公式
Are realrange and einsum really elegant
DMR system solution of Kaiyuan MINGTING hotel of Fengqiao University
quill-editor图片缩放、在一个页面使用多个富文本框、quill-editor上传图片地址为服务器地址
Int8 quantification and inference of onnx model using TRT
江宁医院DMR系统解决方案
直观理解熵
通用型冒泡、选择、插入、希尔、快速排序的代码实现
可视化之路(十)分割画布函数详解
LATEX公式注意事项
大型体育赛事无线通信系统
Warning "force fallback to CPU execution for node: gather_191" in onnxruntime GPU 1.7
南方投资大厦SDC智能通信巡更管理系统
利用mysql-binlog恢复数据
H5案例开发
嵌入式相关面经(一)
el-select 中v-model绑定值,数据回显只显示value,不显示label
应急医疗通讯解决方案|MESH无线自组网系统