【BZOJ3730】震波 - 动态点分治
题意:
Description
不幸的是,这片土地常常发生地震,并且随着时代的发展,城市的价值也往往会发生变动。
接下来你需要在线处理M次操作:
0 x k 表示发生了一次地震,震中城市为x,影响范围为k,所有与x距离不超过k的城市都将受到影响,该次地震造成的经济损失为所有受影响城市的价值和。
1 x y 表示第x个城市的价值变成了y。
为了体现程序的在线性,操作中的x、y、k都需要异或你程序上一次的输出来解密,如果之前没有输出,则默认上一次的输出为0。
Input
第二行包含N个正整数,第i个数表示value[i]。
接下来N-1行,每行包含两个正整数u、v,表示u和v之间有一条无向边。
接下来M行,每行包含三个数,表示M次操作。
$1\leq u,v,x\leq N$
$1\leq value[i],y\leq 10000$
$0\leq k\leq N-1$
Output
包含若干行,对于每个询问输出一行一个正整数表示答案。
题解:
动态点分治裸题……
今天终于弄清楚动态点分治是啥玩意了……就是用数据结构爬点分树,大致感觉其实跟树链剖分差不多?(依稀记得我貌似还有个紫荆花之恋的大坑?!)
这题用RMQLCA+线段树随便维护一下就好了……
ps:我写的ST表求LCA+线段树跑了1600ms……卡常数の不能……orzlhx树状数组+神秘优化跑了543ms
代码:
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#define inf 2147483647
#define eps 1e-9
using namespace std;
typedef long long ll;
struct edge{
int v,next;
}a[];
struct node{
int v,ls,rs;
}t[];
int n,m,op,u,v,x,y,S,rt,ans=,tot=,tim=,cnt=,num[],f[],rt1[],rt2[],head[],mx[],dep[],siz[],dfn[],st[][],lg[];
bool used[];
void add(int u,int v){
a[++tot].v=v;
a[tot].next=head[u];
head[u]=tot;
}
void updata(int l,int r,int &u,int p,int x){
if(!u)u=++cnt;
t[u].v+=x;
if(l==r)return;
int mid=(l+r)/;
if(p<=mid)updata(l,mid,t[u].ls,p,x);
else updata(mid+,r,t[u].rs,p,x);
}
int query(int l,int r,int u,int p){
if(!u)return ;
if(l==r)return t[u].v;
int mid=(l+r)/;
if(p<=mid)return query(l,mid,t[u].ls,p);
else return query(mid+,r,t[u].rs,p)+t[t[u].ls].v;
}
int getdis(int u,int v){
int l=dep[u]+dep[v],tmp;
u=dfn[u];
v=dfn[v];
if(u>v)swap(u,v);
tmp=lg[v-u+];
return l-min(st[u][tmp],st[v-(<<tmp)+][tmp])*;
}
void dfs(int u,int fa,int dpt){
dfn[u]=++tim;
dep[u]=dpt;
st[tim][]=dep[u];
for(int tmp=head[u];tmp!=-;tmp=a[tmp].next){
int v=a[tmp].v;
if(v!=fa){
dfs(v,u,dpt+);
st[++tim][]=dep[u];
}
}
}
void getrt(int u,int fa){
siz[u]=;
mx[u]=;
for(int tmp=head[u];tmp!=-;tmp=a[tmp].next){
int v=a[tmp].v;
if(v!=fa&&!used[v]){
getrt(v,u);
siz[u]+=siz[v];
mx[u]=max(mx[u],siz[v]);
}
}
mx[u]=max(mx[u],S-mx[u]);
if(mx[u]<mx[rt])rt=u;
}
void getn(int u,int fa,int ls){
updata(,n-,rt1[ls],getdis(u,ls),num[u]);
if(f[ls])updata(,n-,rt2[ls],getdis(u,f[ls]),num[u]);
siz[u]=;
for(int tmp=head[u];tmp!=-;tmp=a[tmp].next){
int v=a[tmp].v;
if(v!=fa&&!used[v]){
getn(v,u,ls);
siz[u]+=siz[v];
}
}
}
void divide(int u){
getn(u,,u);
used[u]=true;
for(int tmp=head[u];tmp!=-;tmp=a[tmp].next){
int v=a[tmp].v;
if(!used[v]){
S=siz[v];
rt=;
getrt(v,);
f[rt]=u;
divide(rt);
}
}
}
void LHX_AK_IOI(int u,int k){
for(int now=u;now;now=f[now]){
updata(,n-,rt1[now],getdis(u,now),k-num[u]);
if(f[now])updata(,n-,rt2[now],getdis(u,f[now]),k-num[u]);
}
num[u]=k;
}
int LHX_AK_NOI(int u,int k){
int ret=;
for(int now=u;now;now=f[now]){
if(getdis(u,now)<=k)ret+=query(,n-,rt1[now],k-getdis(u,now));
if(f[now]&&getdis(u,f[now])<=k)ret-=query(,n-,rt2[now],k-getdis(u,f[now]));
}
return ret;
}
int main(){
memset(head,-,sizeof(head));
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)scanf("%d",&num[i]);
for(int i=;i<n;i++){
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
dfs(,,);
lg[]=-;
for(int i=;i<=tim;i++)lg[i]=lg[i>>]+;
for(int i=;(<<i)<=tim;i++){
for(int j=;j<=tim-(<<i)+;j++){
st[j][i]=min(st[j][i-],st[j+(<<i-)][i-]);
}
}
mx[rt=]=inf;
S=n;
getrt(,);
divide(rt);
for(int i=;i<=m;i++){
scanf("%d%d%d",&op,&x,&y);
x^=ans,y^=ans;
if(op==){
ans=LHX_AK_NOI(x,y);
printf("%d\n",ans);
}else LHX_AK_IOI(x,y);
}
return ;
}
【BZOJ3730】震波 - 动态点分治的更多相关文章
- bzoj3730 震波 [动态点分治,树状数组]
传送门 思路 如果没有强制在线的话可以离线之后CDQ分治随便搞. 有了强制在线之后--可能可以二维线段树?然而我不会算空间. 然后我们莫名其妙地想到了动态点分治,然后这题就差不多做完了. 点分树有一个 ...
- BZOJ3730震波——动态点分治+线段树(点分树套线段树)
题目描述 在一片土地上有N个城市,通过N-1条无向边互相连接,形成一棵树的结构,相邻两个城市的距离为1,其中第i个城市的价值为value[i].不幸的是,这片土地常常发生地震,并且随着时代的发展,城市 ...
- BZOJ3730 震波 | 动态点分治
#include <cstdio> #include <cstring> #include <cmath> #include <algorithm> # ...
- bzoj3730 [震波][动态树分治+线段树+LCA]
震波 Time Limit: 15 Sec Memory Limit: 256 MBSubmit: 1573 Solved: 358[Submit][Status][Discuss] Descri ...
- 【BZOJ3730】震波 动态树分治+线段树
[BZOJ3730]震波 Description 在一片土地上有N个城市,通过N-1条无向边互相连接,形成一棵树的结构,相邻两个城市的距离为1,其中第i个城市的价值为value[i].不幸的是,这片土 ...
- 【BZOJ-3730】震波 动态点分治 + 树状数组
3730: 震波 Time Limit: 15 Sec Memory Limit: 256 MBSubmit: 626 Solved: 149[Submit][Status][Discuss] D ...
- 【bzoj3730】震波 动态点分治+线段树
题目描述 在一片土地上有N个城市,通过N-1条无向边互相连接,形成一棵树的结构,相邻两个城市的距离为1,其中第i个城市的价值为value[i].不幸的是,这片土地常常发生地震,并且随着时代的发展,城市 ...
- bzoj 3730: 震波 动态点分治_树链剖分_线段树
##### 题目描述 : 在一片土地上有N个城市,通过N-1条无向边互相连接,形成一棵树的结构,相邻两个城市的距离为1,其中第i个城市的价值为value[i].不幸的是,这片土地常常发生地震,并且随着 ...
- BZOJ 4372/3370 烁烁的游戏/震波 (动态点分治+线段树)
烁烁的游戏 题目大意: 给你一棵$n$个节点的树,有$m$次操作,询问某个节点的权值,或者将与某个点$x$距离不超过$d$的所有节点的权值都增加$w$ 动态点分裸题 每个节点开一棵权值线段树 对于修改 ...
随机推荐
- iOS构建流畅的交互界面--CPU,GPU资源消耗的原因和解决方案
CPU资源消耗的原因和解决方案对象创建轻量对象代替重量对象* 不需要响应触摸事件的控件:CALayer显示* 对象不涉及UI操作,则尽量放到后台线程创建* 包含有CALayer的控件只能在主线程创建和 ...
- Windows10 下安装 Mongodb
一.先登录Mongodb官网https://www.mongodb.com/download-center#community 下载 安装包.32.64位的都行.
- bzoj 1814 Fornula 1
Formula 1 题意 在\(n*m\)的矩阵中,有些格子有树,没有树的格子不能到达,找一条回路,吃完所有的树,求有多少种方法. 解法 因为只要一条回路,所以我们必须维护插头的连通性. 具体的可以参 ...
- [学习笔记] CS131 Computer Vision: Foundations and Applications:Lecture 1 课程介绍
课程大纲:http://vision.stanford.edu/teaching/cs131_fall1718/syllabus.html 课程定位: 课程交叉: what is (computer) ...
- JS数据分组[JSON]
JS 数据分组 var arr = [{ "id": "1001", "name": "值1", "value ...
- Golang 源码剖析:log 标准库
Golang 源码剖析:log 标准库 原文地址:Golang 源码剖析:log 标准库 日志 输出 2018/09/28 20:03:08 EDDYCJY Blog... 构成 [日期]<空格 ...
- 实战:vue项目中导入swiper插件
版本选择 swiper是个常用的插件,现在已经迭代到了第四代:swiper4.常用的版本是swiper3和swiper4,我选择的是swiper3. 安装 安装swiper3的最新版本3.4.2: n ...
- django-10-中间件和上下文管理器
<<<中间件的引入>>> 用户<->中间件<->url->视图 在app目录里面 middleware.py (1)中间件就是一个 ...
- 紫书 例题8-3 UVa 1152(中途相遇法)
这道题要逆向思维, 就是求出答案的一部分, 然后反过去去寻找答案存不存在. 其实很多其他题都用了这道题目的方法, 自己以前都没有发现, 这道题专门考这个方法.这个方法可以没有一直往下求, 可以省去很多 ...
- C#窗体间的跳转传值
1.开发平台VS2012 2.需求:从一个窗体跳转到另一个窗体,并传递参数,接收返回值. 3.案列如图: 4.代码如下: 登陆窗体: //当点击注册按钮 private void button2_Cl ...