动态点分治

考虑从每一个"块"里找到距离k范围内的点的和

为了去重,

每个x维护两个线段树:(都是关于自己分治树子树的点)

1.下标为距离x的距离,权值为val的

2.下标为距离x的分治树father的距离,权值为val

这样,统计的时候

计算分治树祖先块的时候,把从自己那里出来的块的东西再减去

注意:

1.点分治nowrt是全局变量,所以divi这一层用tmp额外记录一下,否则回溯回来再下去的时候,nowrt就不是这一层的了

2.不能某个祖先的dis大于k,就直接break了。因为到分治树祖先的距离没有单调性!!!!

代码:

#include<bits/stdc++.h>
#define il inline
#define reg register int
#define numb (ch^'0')
#define mid ((l+r)>>1)
using namespace std;
typedef long long ll;
il void rd(int &x){char ch;bool fl=false;while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);for(x=numb;isdigit(ch=getchar());x=x*10+numb);(fl==true)&&(x=-x);
}
namespace Miracle{
const int N=100000+5;
int n,m;
struct node{int nxt,to;
}e[2*N];
int hd[N],cnt;
void add(int x,int y){e[++cnt].nxt=hd[x];e[cnt].to=y;hd[x]=cnt;
}
int fa[N];
int sz[N];
int mx[N];
int nowsz;
int tmprt;
int rt[N][2];//0 is myself ; 1 is disfather
int nowrt;
struct tr{int ls,rs;int sum;
}t[N*50];
int tot;
int dist[N][20];
int dep[N];
int val[N];
int vis[N];
void pushup(int x){t[x].sum=t[t[x].ls].sum+t[t[x].rs].sum;
}
void upda(int &x,int l,int r,int p,int v){if(!x) x=++tot;if(l==r){t[x].sum+=v;return;}if(p<=mid) upda(t[x].ls,l,mid,p,v);else upda(t[x].rs,mid+1,r,p,v);pushup(x);
}
int query(int x,int l,int r,int L,int R){//no dis=0 (myself)if(L>R) return 0;if(L<=l&&r<=R){return t[x].sum;}int ret=0;if(L<=mid) ret+=query(t[x].ls,l,mid,L,R);if(mid<R) ret+=query(t[x].rs,mid+1,r,L,R);return ret;
}
void dfs1(int x,int f,int d,int dis){//find nowrtsz[x]=1;mx[x]=0;dep[x]=d;if(d!=1){upda(tmprt,0,n,dis,val[x]);}for(reg i=hd[x];i;i=e[i].nxt){int y=e[i].to;if(vis[y]||y==f) continue;dfs1(y,x,d,dis+1);sz[x]+=sz[y];mx[x]=max(mx[x],sz[y]);}mx[x]=max(mx[x],nowsz-sz[x]);if(mx[x]<=nowsz/2&&(nowsz-sz[x])<=nowsz/2){nowrt=x;}
}
void dfs2(int x,int f,int d,int dis){//find dis from nowrtsz[x]=1;dep[x]=d;dist[x][d]=dis;upda(rt[nowrt][0],0,n,dis,val[x]);for(reg i=hd[x];i;i=e[i].nxt){int y=e[i].to;if(vis[y]||y==f) continue;dfs2(y,x,d,dis+1);sz[x]+=sz[y];}
}
void divi(int x,int d,int f){//mxsz=0;
//    cout<<" x "<<x<<" : "<<d<<" "<<f<<endl;nowrt=0;tmprt=0;dfs1(x,0,d,1);fa[nowrt]=f;rt[nowrt][1]=tmprt;
//    cout<<" nowrt "<<nowrt<<endl;dfs2(nowrt,0,d,0);vis[nowrt]=1;int tmp=nowrt;for(reg i=hd[tmp];i;i=e[i].nxt){int y=e[i].to;if(!vis[y]){nowsz=sz[y];divi(y,d+1,tmp);}}
}
int wrk0(int x,int k){int ret=0;ret+=query(rt[x][0],0,n,0,k);int tmp=x;while(fa[x]){int y=fa[x];//    if(k-dist[tmp][dep[y]]>=0) ret+=query(rt[y][0],0,n,0,k-dist[tmp][dep[y]]);//    else break;ret-=query(rt[x][1],0,n,0,k-dist[tmp][dep[y]]);x=y;}return ret;
}
void wrk1(int x,int v){int tmp=x;int c=v-val[x];val[x]=v;upda(rt[x][0],0,n,0,c);while(fa[x]){int y=fa[x];upda(rt[x][1],0,n,dist[tmp][dep[y]],c);upda(rt[y][0],0,n,dist[tmp][dep[y]],c);x=y;}
}
int main(){rd(n);rd(m);for(reg i=1;i<=n;++i) rd(val[i]);int x,y;for(reg i=1;i<n;++i){rd(x);rd(y);add(x,y);add(y,x);}nowsz=n;divi(1,1,0);
//    cout<<" toot "<<tot<<endl;int op,k;int lasans=0;while(m--){rd(op);rd(x);rd(k);x^=lasans;k^=lasans;if(op==0) printf("%d\n",lasans=wrk0(x,k));else wrk1(x,k);}return 0;
}}
signed main(){
//    freopen("data.in","r",stdin);
//    freopen("my.out","w",stdout);
    Miracle::main();return 0;
}/*Author: *Miracle*Date: 2019/2/6 10:11:29
*/

总结:

动态点分治往往为了去重,经常考虑x对fa的贡献

相当于在分治树的往fa走的边上造了一个线段树

(每个点一个,每个边一个,一共n+n-1个)

转载于:https://www.cnblogs.com/Miracevin/p/10353703.html

bzoj3730. 震波相关推荐

  1. BZOJ3730 震波 【动态点分治】*

    BZOJ3730 震波 Description 在一片土地上有N个城市,通过N-1条无向边互相连接,形成一棵树的结构,相邻两个城市的距离为1,其中第i个城市的价值为value[i]. 不幸的是,这片土 ...

  2. [BZOJ3730]震波(动态点分治)

    3730: 震波 Time Limit: 15 Sec  Memory Limit: 256 MB Submit: 2260  Solved: 470 [Submit][Status][Discuss ...

  3. BZOJ3730 震波+BZOJ4372 烁烁的游戏(动态点分治)

    震波 在一片土地上有N个城市,通过N-1条无向边互相连接,形成一棵树的结构,相邻两个城市的距离为1,其中第i个城市的价值为value[i]. 不幸的是,这片土地常常发生地震,并且随着时代的发展,城市的 ...

  4. [BZOJ3730]震波-动态点分治

    震波 Description 在一片土地上有N个城市,通过N-1条无向边互相连接,形成一棵树的结构,相邻两个城市的距离为1,其中第i个城市的价值为value[i]. 不幸的是,这片土地常常发生地震,并 ...

  5. Bzoj3730 震波

    Time Limit: 15 Sec  Memory Limit: 256 MB Submit: 753  Solved: 176 Description 在一片土地上有N个城市,通过N-1条无向边互 ...

  6. Bzoj3730: 震波

    题面 戳我 Sol 动态点分治: 建个点分树,每个节点开两颗线段树,以与该点的距离为下标,维护价值和 一棵树维护这个点的,一棵维护对上层重心的贡献 然后.. 然后?直接暴力搞就行了 注意常数优化我TL ...

  7. bzoj3730震波

    这是一道动态点分治好题. 在点分树上,对于每个点,维护两个树状数组,一个维护离点分中心距离不超过某个值的点权和,另一个维护离点分中心的父亲距离不超过某个值的点权和.注意树状数组的大小不必开到联通子树的 ...

  8. [BZOJ3730]震波

    题目   点这里看题目.    BZOJ 目测-是炸了. 分析   动态点分治入门题.   首先理解什么叫 " 动态点分治 ".   一般点分治需要离线解决,不带修改.动态点分治可 ...

  9. BZOJ3730 震波 【动态点分治】

    传送门 SOL 点分树模板 细节看注释吧 多写几遍应该就好了 CODE #include<bits/stdc++.h> using namespace std; #define sf sc ...

最新文章

  1. 深度包检测 DPI 介绍
  2. 利用logistic回归构建申请信用评级案例
  3. cview类 public_在MFC单文档的View类中,如何获得指向状态栏的指针
  4. P3708-koishi的数学题【差分】
  5. 算法竞赛入门经典 例题6-2 铁轨(C、python)
  6. 计算机科学的知识领域
  7. 通用的《求职信》范文模板
  8. 配置微软Azure Kinect DK 录制器k4arecorder
  9. 详解Django的CSRF认证
  10. 在html中 标题单元格的标记是,html表格标题标签是什么
  11. Work around for SQL Configuration Manager Consol
  12. python 矩阵求转置、行列式、迹、求逆
  13. 笔记本亮度无法调节的可能原因
  14. 【考试记录】阿里云DevOps助理工程师(ACA)
  15. matlab在命令行注册,在命令行窗口中输入语句
  16. git revert回退时提示One or more files are in a conflicted state
  17. java byte与char互转原理_java byte与char互转原理
  18. 电感与磁珠(补充中)
  19. 大型互联网系统架构演进之路
  20. ios微信软键盘之殇

热门文章

  1. 【新品发布】研扬科技首款深度学习AI服务器——AI Machine ARC-628横空问世
  2. 海思ubootsd卡协议
  3. 2014年重要的软件开发发展
  4. 【bzoj2563】 阿狸和桃子的游戏 贪心
  5. Android捕捉崩溃日志并输出日志文件
  6. H5移动端rem布局还原750px设计稿方案。
  7. OpenGL使用矩阵堆栈glpushMatrix的原因
  8. python随机数列表变成字符串_DAY8 for Python--字符串与随机数
  9. 电压跟随器的概念及使用总结
  10. 贝佐斯:要想80岁之前没有遗憾 问问自己下面12个问题