震波

在一片土地上有N个城市,通过N-1条无向边互相连接,形成一棵树的结构,相邻两个城市的距离为1,其中第i个城市的价值为value[i]。
不幸的是,这片土地常常发生地震,并且随着时代的发展,城市的价值也往往会发生变动。
接下来你需要在线处理M次操作:
0 x k 表示发生了一次地震,震中城市为x,影响范围为k,所有与x距离不超过k的城市都将受到影响,该次地震造成的经济损失为所有受影响城市的价值和。
1 x y 表示第x个城市的价值变成了y。
为了体现程序的在线性,操作中的x、y、k都需要异或你程序上一次的输出来解密,如果之前没有输出,则默认上一次的输出为0。

Input

第一行包含两个正整数N和M。
第二行包含N个正整数,第i个数表示value[i]。
接下来N-1行,每行包含两个正整数u、v,表示u和v之间有一条无向边。
接下来M行,每行包含三个数,表示M次操作。

Output

包含若干行,对于每个询问输出一行一个正整数表示答案。

Sample Input

8 1 1 10 100 1000 10000 100000 1000000 10000000 1 2 1 3 2 4 2 5 3 6 3 7 3 8 0 3 1

Sample Output

11100101

Hint

1<=N,M<=100000

1<=u,v,x<=N

1<=value[i],y<=10000

0<=k<=N-1

题解

首先想到动态点分治+线段树

我们这时显然不能维护dfs序上的权值

我们可以对到当前点分中心的距离来开一个线段树

如果当前点分中心为u

那么线段树需要维护距离点u为 i 的所有点的权值之和

但是我们可能会算重,有可能点分中心的父亲会再一次计算某一些点的点权和

所有我们考虑如何去重

我们可以对点 u 再用一个线段树维护它的子树节点到它的点分树父亲的距离为 i 的点权和

在查询的时候减掉会被父亲计算的点的点权和即可

(强制在线,RE一般就是WA了,当然也有可能是真RE了)

代码:(查出来无数个sb错,还是一直RE,最后发现自己的动态开点线段树没有判等。。。)

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
inline int gi()
{char c;int num=0;while((c=getchar())<'0'||c>'9');while(c>='0'&&c<='9'){num=num*10+c-48;c=getchar();}return num;
}
#define N 100005
#define LOG 17
#define lc a[i].l,l,mid
#define rc a[i].r,mid+1,r
const int INF=0x3f3f3f3f;
int n,m;
int fir[N],to[2*N],nxt[2*N],cnt;
int val[N];
int tmpsiz[N],nrt,all;bool vis[N];
int dis[LOG][N],dfa[N],dep[N];
struct node{int l,r,x;}a[N*66];
int T1[N],T2[N],tot;
inline void adde(int a,int b)
{to[++cnt]=b;nxt[cnt]=fir[a];fir[a]=cnt;to[++cnt]=a;nxt[cnt]=fir[b];fir[b]=cnt;
}
void insert(int &i,int l,int r,int x,int k)
{if(!i)i=++tot;a[i].x+=k;if(l==r)return;int mid=(l+r)>>1;if(x<=mid)insert(lc,x,k);else insert(rc,x,k);
}
int query(int i,int l,int r,int qr)
{if(!i)return 0ll;if(l==r)return a[i].x;int mid=(l+r)>>1;if(qr<=mid)return query(lc,qr);else return a[a[i].l].x+query(rc,qr);
}
void findrt(int u,int ff)
{int mx=0;tmpsiz[u]=1;for(int v,p=fir[u];p;p=nxt[p]){if(!vis[v=to[p]]&&v!=ff){findrt(v,u);tmpsiz[u]+=tmpsiz[v];mx=max(mx,tmpsiz[v]);}}mx=max(mx,all-tmpsiz[u]);if(2*mx<=all)nrt=u;
}
inline int getrt(int u,int sz)
{nrt=-INF;all=sz;findrt(u,0);return nrt;
}
void pre(int u,int ff,int d,int rt)
{insert(T1[rt],0,n-1,dis[d][u],val[u]);if(dfa[rt])insert(T2[rt],0,n-1,dis[d-1][u],val[u]);//tmpsiz[u]=1;for(int v,p=fir[u];p;p=nxt[p]){if(!vis[v=to[p]]&&v!=ff){dis[d][v]=dis[d][u]+1;pre(v,u,d,rt);tmpsiz[u]+=tmpsiz[v];}}
}
void DFZ(int u,int d)
{vis[u]=1;dep[u]=d;dis[d][u]=0;pre(u,0,d,u);for(int v,p=fir[u];p;p=nxt[p]){if(!vis[v=to[p]]){dfa[v=getrt(v,tmpsiz[v])]=u;DFZ(v,d+1);}}
}
inline void modify(int u,int k)
{for(int t=u;t;t=dfa[t]){insert(T1[t],0,n-1,dis[dep[t]][u],k-val[u]);//if(dfa[t])insert(T2[t],0,n-1,dis[dep[t]-1][u],k-val[u]);//}val[u]=k;
}
inline int query(int u,int k)
{long long ans=0;for(int t=u;t;t=dfa[t]){if(dfa[t]&&dis[dep[t]-1][u]<=k) ans-=query(T2[t],0,n-1,k-dis[dep[t]-1][u]);//if(dis[dep[t]][u]<=k) ans+=query(T1[t],0,n-1,k-dis[dep[t]][u]);//}return int(ans);
}
int main()
{int i,op,u,v;int ans=0;n=gi();m=gi();for(i=1;i<=n;i++)val[i]=gi();for(i=1;i<n;i++){u=gi();v=gi();adde(u,v);}DFZ(getrt(1,n),0);for(i=1;i<=m;i++){op=gi();u=gi();v=gi();u^=ans;v^=ans;if(op)modify(u,v);else printf("%d\n",ans=query(u,v));}
}

烁烁的游戏

背景:烁烁很喜欢爬树,这吓坏了树上的皮皮鼠。
题意:
给定一颗n个节点的树,边权均为1,初始树上没有皮皮鼠。
烁烁他每次会跳到一个节点u,把周围与他距离不超过d的节点各吸引出w只皮皮鼠。皮皮鼠会被烁烁吸引,所以会一直待在节点上不动。
烁烁很好奇,在当前时刻,节点u有多少个他的好朋友---皮皮鼠。
大意:
给一颗n个节点的树,边权均为1,初始点权均为0,m次操作:
Q x:询问x的点权。
M x d w:将树上与节点x距离不超过d的节点的点权均加上w。

Input

第一行两个正整数:n,m
接下来的n-1行,每行三个正整数u,v,代表u,v之间有一条边。
接下来的m行,每行给出上述两种操作中的一种。

Output

对于每个Q操作,输出当前x节点的皮皮鼠数量。

Sample Input

7 6 1 2 1 4 1 5 2 3 2 7 5 6 M 1 1 2 Q 5 M 2 2 3 Q 3 M 1 2 1 Q 2

Sample Output

2 3 6

Hint

数据范围:

n,m<=10^5,|w|<=10^4

注意:w不一定为正整数,因为烁烁可能把皮皮鼠吓傻了。

题解

这题就是上一道题的逆向版

上一道题:单点修改、前缀查询(好像可以用动态开点树状数组)

这一道题:前缀修改、单点查询

直接差分一下,变成单点修改、后缀查询(其实也可以单点修改两次,前缀查询,但是常数会大一些吧。。。。)

然后直接上动态点分治了,基本和上一题一样

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
inline int gi()
{char c;int num=0,flg=1;while((c=getchar())<'0'||c>'9')if(c=='-')flg=-1;while(c>='0'&&c<='9'){num=num*10+c-48;c=getchar();}return num*flg;
}
#define N 100005
#define LOG 17
const int INF=0x3f3f3f3f;
int n,m;
int fir[N],to[2*N],nxt[2*N],cnt;
void adde(int a,int b)
{to[++cnt]=b;nxt[cnt]=fir[a];fir[a]=cnt;to[++cnt]=a;nxt[cnt]=fir[b];fir[b]=cnt;
}
int tmpsiz[N],nrt,all;bool vis[N];
int dis[LOG][N],dfa[N],dep[N];
void findrt(int u,int ff)
{int mx=0;tmpsiz[u]=1;for(int v,p=fir[u];p;p=nxt[p]){if(!vis[v=to[p]]&&v!=ff){findrt(v,u);tmpsiz[u]+=tmpsiz[v];mx=max(mx,tmpsiz[v]);}}mx=max(mx,all-tmpsiz[u]);if(mx+mx<=all)nrt=u;
}
int getrt(int u,int sz)
{nrt=-INF;all=sz;findrt(u,0);return nrt;
}
#define lc a[i].l
#define rc a[i].r
struct node{int l,r,x;}a[N<<7];
int T1[N],T2[N],tot;
void insert(int &i,int l,int r,int x,int k)
{if(!i)i=++tot;a[i].x+=k;if(l==r)return;int mid=(l+r)>>1;if(x<=mid)insert(lc,l,mid,x,k);else insert(rc,mid+1,r,x,k);
}
int query(int i,int l,int r,int ql)
{if(!i)return 0;if(l==r)return a[i].x;int mid=(l+r)>>1;if(ql<=mid)return query(lc,l,mid,ql)+a[rc].x;else return query(rc,mid+1,r,ql);
}
void pre(int u,int ff,int d)
{tmpsiz[u]=1;for(int v,p=fir[u];p;p=nxt[p]){if(!vis[v=to[p]]&&v!=ff){dis[d][v]=dis[d][u]+1;pre(v,u,d);tmpsiz[u]+=tmpsiz[v];}}
}
void DFZ(int u,int d)
{vis[u]=1;dep[u]=d;pre(u,0,d);for(int v,p=fir[u];p;p=nxt[p]){if(!vis[v=to[p]]){dfa[v=getrt(v,tmpsiz[v])]=u;DFZ(v,d+1);}}
}
inline void modify(int u,int k,int s)
{for(int t=u;t;t=dfa[t]){if(dis[dep[t]][u]<=k) insert(T1[t],0,n,k-dis[dep[t]][u],s);//if(dfa[t]&&dis[dep[t]-1][u]<=k) insert(T2[t],0,n,k-dis[dep[t]-1][u],s);//}
}
inline int query(int u)
{long long ans=0;for(int t=u;t;t=dfa[t]){ans+=query(T1[t],0,n,dis[dep[t]][u]);//if(dfa[t]) ans-=query(T2[t],0,n,dis[dep[t]-1][u]);//}return int(ans);
}
char op[3];
int main()
{int i,u,v,s;n=gi();m=gi();for(i=1;i<n;i++){u=gi();v=gi();adde(u,v);}DFZ(getrt(1,n),0);for(i=1;i<=m;i++){scanf("%s",op);if(op[0]=='M'){u=gi();v=gi();s=gi();modify(u,v,s);}else printf("%d\n",query(gi()));}
}

BZOJ3730 震波+BZOJ4372 烁烁的游戏(动态点分治)相关推荐

  1. [BZOJ4372][烁烁的游戏][动态树分治+线段树+LCA]

    [BZOJ4372][烁烁的游戏][动态树分治+线段树+LCA] 题目大意: 给定一颗nn个节点的树,边权均为11,初始每个点权值为00 . 其中操作QQ xx询问x点的点权,操作 MM xx dd ...

  2. bzoj4372 烁烁的游戏 动态点分治+线段树

    Description 背景:烁烁很喜欢爬树,这吓坏了树上的皮皮鼠. 给定一颗n个节点的树,边权均为1,初始树上没有皮皮鼠. 烁烁他每次会跳到一个节点u,把周围与他距离不超过d的节点各吸引出w只皮皮鼠 ...

  3. BZOJ4372: 烁烁的游戏(动态点分治)

    Description 背景:烁烁很喜欢爬树,这吓坏了树上的皮皮鼠. 题意: 给定一颗n个节点的树,边权均为1,初始树上没有皮皮鼠. 烁烁他每次会跳到一个节点u,把周围与他距离不超过d的节点各吸引出w ...

  4. 【BZOJ4372】烁烁的游戏 动态树分治+线段树

    [BZOJ4372]烁烁的游戏 Description 背景:烁烁很喜欢爬树,这吓坏了树上的皮皮鼠. 题意: 给定一颗n个节点的树,边权均为1,初始树上没有皮皮鼠. 烁烁他每次会跳到一个节点u,把周围 ...

  5. 【bzoj4372】烁烁的游戏 动态点分治+线段树

    题目描述 给一颗n个节点的树,边权均为1,初始点权均为0,m次操作: Q x:询问x的点权. M x d w:将树上与节点x距离不超过d的节点的点权均加上w. 输入 第一行两个正整数:n,m 接下来的 ...

  6. bzoj 4372: 烁烁的游戏 动态点分治_树链剖分_线段树

    [Submit][Status][Discuss] Description 背景:烁烁很喜欢爬树,这吓坏了树上的皮皮鼠. 题意: 给定一颗n个节点的树,边权均为1,初始树上没有皮皮鼠. 烁烁他每次会跳 ...

  7. bzoj 4372 烁烁的游戏 —— 动态点分治+树状数组

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4372 本以为和 bzoj3730 一样,可以直接双倍经验了: 但要注意一下,树状数组不能查询 ...

  8. bzoj 4372 烁烁的游戏——动态点分治+树状数组

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4372 和 bzoj 3070 震波 是一个套路.注意区间修改的话,树状数组不能表示 dis ...

  9. [bzoj4372]烁烁的游戏

    [bzoj4372]烁烁的游戏 动态点分,需要注意的是我们对于每个点要开两个数组,另外一个相当于一个容斥,即把他父亲上的减掉. 代码 #include<bits/stdc++.h> usi ...

最新文章

  1. 2009第二届C++技术大会即将在上海隆重召开
  2. Unity设置AppIcon方法
  3. 分享一下@Override标签背后的小秘密---记录java的思行合一
  4. swoole client php,Swoole Client
  5. stm32之ADC应用实例(单通道、多通道、基于DMA)
  6. windows7 安装IIS没有default web site 解决方法
  7. unity循环滚动列表_【unity游戏开发】LoopScrollRect组件
  8. 【系统架构设计师】2020-08-05
  9. Javascript-Switch
  10. 思维导图系列之Java多线程知识梳理
  11. c++ 内存泄露检测
  12. 如何构建一个县的shp图?R语言和Global mapper
  13. 每天吃多少才不会胖?食物和卡路里对照表
  14. 关于http响应200 OK的问题
  15. C#隐藏任务管理器中进程 支持win10 win8.1 win7
  16. 未来智能酒店里 智能管家将24小时待命
  17. 论文翻译 | TOOD:《TOOD: Task-aligned One-stage Object Detection》详细解读
  18. 图像处理之_ARToolKit自定义Marker
  19. 云计算技术,主要包括哪些关键技术?
  20. dos2unix 解决脚本执行过程中的莫名错误 “not found”

热门文章

  1. dll修复精灵无法链接服务器,教你一键dll修复精灵怎么使用
  2. 自制动漫小姐姐图片api
  3. 奥鹏 大工21秋《计算机网络技术》在线作业
  4. 大二的第一次社会毒打
  5. cpu计算机词汇中文意思是,CPU计算机口译词汇中英文对照1
  6. FastDFS合并存储策略
  7. 【Ice】【01】linux 安装ice
  8. Java什么时候会触发类初始化及原理(详解)
  9. android仿照网易新闻源代码
  10. Lombok使用以及优缺点