首页 > 其他分享 >luogu P6329 【模板】点分树 | 震波

luogu P6329 【模板】点分树 | 震波

时间:2024-05-06 16:14:52浏览次数:23  
标签:pre int luogu P6329 震波 res now 点分树

//【模板】点分树 | 震波
//https://www.luogu.com.cn/problem/P6329
#include<bits/stdc++.h>
#define debug(a) cerr<<"Line: "<<__LINE__<<" "#a<<endl
#define print(a) cerr<<#a"="<<(a)<<endl
#define sign() puts("---------")
#define inf 0x3f3f3f3f
using namespace std;
const int N = 1e5 + 10;
int n,q,a[N];
struct Graph{
	int head[N],etot;
	struct node{ int nxt,v; }edge[N<<1];
	void add(int u,int v){
		edge[++etot] = {head[u],v};
		head[u] = etot;
	}
	node & operator [](const int &i){ return edge[i]; }
}G;
int st[N][20],dep[N];
void dfs(int u,int fa){
	st[u][0] = fa, dep[u] = dep[fa] + 1;
	for(int i = 1;(1<<i)<=dep[u];++i)st[u][i] = st[st[u][i-1]][i-1];
	for(int i = G.head[u];i;i = G[i].nxt)if(G[i].v != fa)dfs(G[i].v,u);
}
void scan(){
	scanf("%d%d",&n,&q);
	for(int i = 1;i<=n;++i)scanf("%d",&a[i]);
	for(int i = 1,u,v;i<n;++i){
		scanf("%d%d",&u,&v);
		G.add(u,v),G.add(v,u);
	}
}
int mx[N],root,Tsiz,nwfa[N],siz[N];
bool vis[N];
void getroot(int u,int fa){
	siz[u] = 1, mx[u] = 0;
	for(int i = G.head[u];i;i = G[i].nxt){
		int v = G[i].v;
		if(v != fa && !vis[v]){
			getroot(v,u);
			siz[u] += siz[v];
			mx[u] = max(mx[u],siz[v]);
		}
	}
	mx[u] = max(mx[u],Tsiz - siz[u]);
	if(mx[u] < mx[root])root = u;
}
void solve(int u){
	vis[u] = 1;
	for(int i = G.head[u];i;i = G[i].nxt){
		int v = G[i].v;
		if(!vis[v]){
			root = 0;
			Tsiz = siz[v];
			getroot(v,u);
			nwfa[root] = u;
			solve(root);
		}
	}
}
void init(){
	mx[(root = 0)] = inf;
	Tsiz = n; getroot(1,0); solve(root);
}
int LCA(int x,int y){
	if(dep[x] > dep[y])swap(x,y);
	int t = dep[y] - dep[x];
	for(int i = 17;~i;--i)if(t & (1<<i))y = st[y][i];
	if(x == y)return x;
	for(int i = 17;~i;--i)if(st[x][i] && st[y][i] && st[x][i] != st[y][i])
		x = st[x][i], y = st[y][i];
	return st[x][0];
}
int Dis(int x,int y){ return dep[x] + dep[y] - (dep[LCA(x,y)]<<1); }
struct Segment_tree{
	int rt[N],tot;
	struct Date{ int ls,rs,val; }tr[N*50];
	void pushup(int p){ tr[p].val = tr[tr[p].ls].val + tr[tr[p].rs].val; }
	void modify(int &p,int l,int r,int x,int v){
		if(!p)p = ++tot;
		if(l == r)return tr[p].val += v,void();
		int mid = (l+r)>>1;
		if(x <= mid)modify(tr[p].ls,l,mid,x,v);
		else modify(tr[p].rs,mid+1,r,x,v);
		pushup(p);
	}
	int query(int p,int l,int r,int L,int R){
		if(!p)return 0;
		if(L <= l && r <= R)return tr[p].val;
		int mid = (l+r)>>1;
		int res = 0;
		if(L <= mid)res += query(tr[p].ls,l,mid,L,R);
		if(mid < R)res += query(tr[p].rs,mid+1,r,L,R);
		return res;
	}
}seg1,seg2;
void update(int x,int v){
	int now = x;
	while(now){
		seg1.modify(seg1.rt[now],0,n-1,Dis(now,x),v);
		if(nwfa[now])seg2.modify(seg2.rt[now],0,n-1,Dis(nwfa[now],x),v);
		now = nwfa[now];
	}
} 
int query(int x,int k){
	int now = x, pre = 0, res = 0;
	while(now){
		if(Dis(now,x) > k){
			pre = now, now = nwfa[now];
			continue;
		}
		res += seg1.query(seg1.rt[now],0,n-1,0,k-Dis(now,x));
		if(pre)res -= seg2.query(seg2.rt[pre],0,n-1,0,k-Dis(now,x));
		pre = now, now = nwfa[now];
	}
	return res;
}
int main(){
	scan();
	dfs(1,0);
	init();
	for(int i = 1;i<=n;++i)update(i,a[i]);
	int pre = 0,op,x,y;
	while(q--){
		scanf("%d%d%d",&op,&x,&y);
		x ^= pre, y ^= pre;
		if(op == 1)update(x,y-a[x]),a[x] = y;
		else{
			pre = query(x,y);
			printf("%d\n",pre);
		}
	}
	return 0;
}

标签:pre,int,luogu,P6329,震波,res,now,点分树
From: https://www.cnblogs.com/fight-for-humanity/p/18175175

相关文章

  • [分块] [Luogu AT_joisc2014_c] 历史研究
    题目描述IOI国历史研究的第一人——JOI教授,最近获得了一份被认为是古代IOI国的住民写下的日记。JOI教授为了通过这份日记来研究古代IOI国的生活,开始着手调查日记中记载的事件。日记中记录了连续\(N\)天发生的事件,大约每天发生一件。事件有种类之分。第\(i\)天发生的......
  • 树上点差分的经典应用 LuoguP3258松鼠的新家
    树上点差分的核心就是如何避免重复,即正确的运用差分数组例如a,b点路径上点权值加1,则把a,b路径找到,并找到其LCA,此时可以把a到根,b到根这两条路径看出两条链,把每条链看出我们熟悉的顺序差分结构.以其中一条链为例子,把a当成数组的起点,根当成数组的末尾,进行差分,显然有C[a]+......
  • 点分树(动态点分治)学习笔记
    1.定义在点分治的基础上加以变化,构造一颗支持快速修改的重构树,称之为点分树2.算法2.1.思路点分治的核心在于通过树的重心来划分联通块,减少合并层数,从而降低时间复杂度所以,我们可以按分治递归的顺序提出一颗树,易知树高至多为logn具体的说,对于每一个找到的重心,将上一次分治......
  • [DS 小计] 点分树
    点分树是一个处理树上距离的优秀DS。它可以快速处理关于一些树上距离问题。引入我们知道,我们在做点分治的时候,每次找到中心,然后将重心所有的相连的边断开,处理子问题。时间复杂度是\(O(n\logn)\)的。但是有些题目让我们搞强制在线,又要求距离为\(k\)的所有和,这时候点分树......
  • [POI2007] [LUOGU P3451]旅游景点 Tourist Attractions
    本题解由于作者太菜在POI及LUOGU上会TLE,该题解主要讲思路,剩下的内存优化请各位大佬自行补充,欢迎评论区讨论本题解运行时间10406ms,空间194584KiB题目描述FGD想从成都去上海旅游。在旅途中他希望经过一些城市并在那里欣赏风景,品尝风味小吃或者做其他的有趣的事情。经过这些城......
  • luoguP1024-二分
    题目链接实数二分:实数二分不存在边界问题,二分时可以设立循环次数或确立精度1.若存在2个数x1和x2,且x1<x2,f(x1)×f(x2)<0之间一定存在它的一个浮点数根2.且题目给定实根范围在-100~100之间,按位枚举方程=0时,显然x是方程的一个整数实根题目描述有形如:ax3+bx2+cx+d=0这样......
  • luoguP1102-双指针
    题目链接:P1102A-B数对-洛谷|计算机科学教育新生态(luogu.com.cn)利用单调性求解双指针解法:排序构造出区间单调,则若存在目标值B,B在序列中一定为连续区间,此时通过双指针l和r,此时维护一段区间:有S[L]大于S[I]-C,S[R]大于等于S[I]-C,此时我们枚举每一位,若存在A......
  • Luogu P8710 [蓝桥杯 2020 省 AB1] 网络分析 题解 [ 绿 ] [ 带权并查集 ]
    原题分析本题由于从一个节点发信息,同一个集合内的所有点都会收到信息,显然是一道要求维护各节点间关系的题,因此采用并查集的数据结构进行求解。但由于维护关系的同时还要维护权值,所以采用带权并查集,它是一种能维护某个节点与其祖宗节点之间关系的数据结构。带权并查集找父亲的......
  • Luogu P3294 背单词
    观前须知本题解全部内容遵循CCBY-NC-SA4.0Deed原则同步发布于Luogu题解区更好的观看体验点这里笔者的博客主页正文LuoguP3294【SCOI2016】背单词笔者在刷题的时候看到了这道好题花了四十分钟切掉以后,看了一下题解发现自己的想法不太一样所以想做一篇适合我这样的......
  • luogu P1543 [POI2004] SZP 题解
    题目传送门前置知识树形DP解法将\(a_{i}\)向\(i\)连一条有向边,这样就形成了基环外向树森林。基环外向树森林内每棵基环外向树是相互独立的,需要单独处理。对于每棵基环外向树,任取环上一点\(x\),断开\(x\)到\(fa_{x}\)的有向边,外向树就变成了一棵以\(x\)为根的树。......