[bzoj3730][動態點分治][線段樹]震波
Description
在一片土地上有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
題解
學一手動態點分治
需要一棵點分樹
容易發現,點分樹的樹高只有
動態點分治就是考慮在這上面搞事
先單考慮在原樹上的過程,我們可以每次向上跳一個祖先,然後記錄距離他是K-1的點
這樣會記重 於是你要減去當前距離上一個祖先也是K-1的點
拓展到點分樹上也是一樣的
每個點開兩顆線段樹 記錄距離自己的值的點和距離點分樹上上一個祖先的點
每個跳就行了
然後
這題卡常數啊
我的9K程式碼硬是沒卡過去
有沒有大爺伸出援手的鴨…
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<ctime>
#include<map>
#include<bitset>
#define LL long long
#define mp(x,y) make_pair(x,y)
#define pll pair<long long,long long>
#define pii pair<int,int>
using namespace std;
inline char nc() {
static char buf[1000000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
}
inline int read(void) {
char ch=nc();
int sum=0;
while(!(ch>='0'&&ch<='9'))
ch=nc();
while(ch>='0'&&ch<='9')
sum=(sum<<3)+(sum<<1)+(ch^48),ch=nc();
return sum;
}
static int stack[20];
inline void write(int x)
{
if(x<0){putchar('-');x=-x;}
if(!x){putchar('0');return;}
int top=0;
while(x)stack[++top]=x%10,x/=10;
while(top)putchar(stack[top--]+'0');
}
inline void pr1(int x){write(x);putchar(' ');}
inline void pr2(int x){write(x);putchar('\n');}
const int MAXN=100005;
struct node{int y,next;}a[MAXN*2];int len,last[MAXN];
void ins(int x,int y){len++;a[len].y=y;a[len].next=last[x];last[x]=len;}
int dfn[2*MAXN],dep[MAXN],fir[MAXN],id,mn[25][2*MAXN],bin[25],n,Log[2*MAXN];
void pre_tree_node(int x,int fa)
{
dfn[++id]=x;fir[x]=id;
for(int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
if(y!=fa)
{
dep[y]=dep[x]+1;
pre_tree_node(y,x);
dfn[++id]=x;
}
k=a[k].next;if(!k)break;
y=a[k].y;
if(y!=fa)
{
dep[y]=dep[x]+1;
pre_tree_node(y,x);
dfn[++id]=x;
}
k=a[k].next;if(!k)break;
y=a[k].y;
if(y!=fa)
{
dep[y]=dep[x]+1;
pre_tree_node(y,x);
dfn[++id]=x;
}
k=a[k].next;if(!k)break;
y=a[k].y;
if(y!=fa)
{
dep[y]=dep[x]+1;
pre_tree_node(y,x);
dfn[++id]=x;
}
}
}
inline void init()
{
for(int i=1;i<=id;i++)mn[0][i]=i;
for(int i=1;bin[i]<=id;i++)
for(int x=1;x+bin[i]-1<=id;x++)
mn[i][x]=dep[dfn[mn[i-1][x]]]<dep[dfn[mn[i-1][x+bin[i-1]]]]?mn[i-1][x]:mn[i-1][x+bin[i-1]];
}
inline int lca(int x,int y)
{
if(fir[x]>fir[y])swap(x,y);
x=fir[x];y=fir[y];int K=Log[y-x+1];
return dep[dfn[mn[K][x]]]<dep[dfn[mn[K][y-bin[K]+1]]]?dfn[mn[K][x]]:dfn[mn[K][y-bin[K]+1]];
}
inline int dis(int x,int y)
{
int LA=lca(x,y);
return dep[x]+dep[y]-2*dep[LA];
}
//LCA
int cal[MAXN],lin[MAXN],now,nxt;
int rt1[MAXN],rt2[MAXN];
int maxdep,mindep,tim,cnt[MAXN],vi[MAXN];
struct segtree
{
int lc[MAXN*30],rc[MAXN*30],sum[MAXN*30],tot;
void buildtree(int &now,int l,int r)
{
if(l>maxdep)return ;
if(!now)now=++tot;
if(l==r){sum[now]=cnt[l];return ;}
int mid=(l+r)/2;
buildtree(lc[now],l,mid);buildtree(rc[now],mid+1,r);
sum[now]=sum[lc[now]]+sum[rc[now]];
}
void modify(int &now,int l,int r,int p,int c)
{
if(!now)now=++tot;sum[now]+=c;
if(l==r)return ;
int mid=(l+r)/2;
if(p<=mid)modify(lc[now],l,mid,p,c);
else modify(rc[now],mid+1,r,p,c);
}
int query(int now,int l,int r,int ql,int qr)
{
if(!now)return 0;
if(l==ql&&r==qr)return sum[now];
int mid=(l+r)/2;
if(qr<=mid)return query(lc[now],l,mid,ql,qr);
else if(mid+1<=ql)return query(rc[now],mid+1,r,ql,qr);
else return query(lc[now],l,mid,ql,mid)+query(rc[now],mid+1,r,mid+1,qr);
}
}seg1,seg2;
//seg
bool vis[MAXN];
int refa[MAXN],to[MAXN],mx[MAXN],G,sum;
inline int getsiz(int x,int fa)
{
int re=1;
for(register int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
if(y!=fa&&vis[y])re+=getsiz(y,x);
k=a[k].next;if(!k)break;
y=a[k].y;
if(y!=fa&&vis[y])re+=getsiz(y,x);
k=a[k].next;if(!k)break;
y=a[k].y;
if(y!=fa&&vis[y])re+=getsiz(y,x);
k=a[k].next;if(!k)break;
y=a[k].y;
if(y!=fa&&vis[y])re+=getsiz(y,x);
}
return re;
}
inline void go(int x,int fa)
{
to[x]=mx[x]=1;
for(register int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
if(y!=fa&&vis[y])
{
go(y,x);to[x]+=to[y];
mx[x]=max(mx[x],to[y]);
}
k=a[k].next;if(!k)break;
y=a[k].y;
if(y!=fa&&vis[y])
{
go(y,x);to[x]+=to[y];
mx[x]=max(mx[x],to[y]);
}
k=a[k].next;if(!k)break;
y=a[k].y;
if(y!=fa&&vis[y])
{
go(y,x);to[x]+=to[y];
mx[x]=max(mx[x],to[y]);
}
k=a[k].next;if(!k)break;
y=a[k].y;
if(y!=fa&&vis[y])
{
go(y,x);to[x]+=to[y];
mx[x]=max(mx[x],to[y]);
}
}
mx[x]=max(mx[x],sum-to[x]);
if(mx[x]<mx[G]||!G)G=x;
}
inline void newnode(int x,int fa,int d)
{
maxdep=max(maxdep,d);mindep=min(mindep,d);
if(vi[d]!=tim)vi[d]=tim,cnt[d]=0;
cnt[d]+=lin[x];
for(int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
if(y!=fa&&vis[y])newnode(y,x,d+1);
k=a[k].next;if(!k