树剖学习 (2) & 做题记录 P3950 部落冲突

封面


不要问我 (11) 去哪里了,在咕咕咕


全文字


看完后可以看着下面的图再自己独立推一次。

少文字


看完后完成 P3950

P3950 代码
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define itn int
#define ull unsigned long long
const int MN=3*1e5+10;
LL tree[MN*8],tag[MN*8];
int n,m,p,q,x;
char op;
vector<int>tu[MN];
int fa[MN],top[MN],dep[MN],son[MN],siz[MN],id[MN],idx;
int root=1,k=0;
vector<pair<int,int>>E/*vent*/;
void dfs(int &now,int &fat){
fa[now]=fat;dep[now]=dep[fat]+1;siz[now]=1;
for(auto &x:tu[now]){
if(x!=fat){
dfs(x,now);
siz[now]+=siz[x];
if(siz[x]>siz[son[now]]){
son[now]=x;
}
}
}
return;
}
void dfs2(int &now,int &fr){
id[now]=++idx;top[now]=fr;
if(son[now])dfs2(son[now],fr);
for(auto &x:tu[now]){
if(x!=son[now]&&x!=fa[now]){
dfs2(x,x);
}
}
return;
}
void push_up(int &now){
tree[now]=tree[now*2]+tree[now*2+1];
return;
}
void push_down(int &now,int &ll,int &lr,int rl,int &rr){
if(!tag[now])return;
tag[now*2]+=tag[now];
tag[now*2+1]+=tag[now];
tree[now*2]+=(lr-ll+1)*tag[now];
tree[now*2+1]+=(rr-rl+1)*tag[now];
tag[now]=0;
return;
}
bool inli(int &l,int &r,int &xl,int &xr){
return l>=xl&&xr>=r;
}
void change(int now,int l,int &r,int &xl,int &xr,int &add){
if(inli(l,r,xl,xr)){
tree[now]+=(r-l+1)*add;
tag[now]+=add;
return;
}
int mid=l+(r-l)/2;
push_down(now,l,mid,mid+1,r);
if(mid>=xl)change(now*2,l,mid,xl,xr,add);
if(mid<xr)change(now*2+1,mid+1,r,xl,xr,add);
push_up(now);
return;
}
LL query(int now,int l,int &r,int &xl,int &xr){
if(inli(l,r,xl,xr)){
return tree[now];
}
LL sum=0;
int mid=l+(r-l)/2;
push_down(now,l,mid,mid+1,r);
if(mid>=xl)sum+=query(now*2,l,mid,xl,xr);
if(mid<xr)sum+=query(now*2+1,mid+1,r,xl,xr);
push_up(now);
return sum;
}
LL get_query(int &x,int &y){
LL sum=0;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
sum+=query(1,1,n,id[top[x]],id[x]);
x=fa[top[x]];
if(sum>0)return 1;
//cout<<x<<" "<<y<<"\n";
}
if(id[x]<id[y])swap(x,y);
int l=id[y]+1;
if(id[y]+1<=id[x])sum+=query(1,1,n,l,id[x]);
return sum;
}
void get_change(int &x,int &y,int add){
// while(top[x]!=top[y]){
// if(dep[top[x]]<dep[top[y]])swap(x,y);
// change(1,1,n,top[x],id[x],add);
// x=fa[top[x]];
// cout<<x<<" "<<y<<"\n";
// }
if(id[x]<id[y])swap(x,y);
change(1,1,n,id[x],id[x],add);
return;
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>n>>m;
for(int i=1;i<n;i++){
cin>>p>>q;
tu[p].emplace_back(q);
tu[q].emplace_back(p);
}
dfs(root,k);
dfs2(root,root);
while(m--){
cin>>op;
if(op=='Q'){
cin>>p>>q;
cout<<(get_query(p,q)==0?"Yes\n":"No\n");
}
else if(op=='C'){
cin>>p>>q;
get_change(p,q,1);
E.push_back({p,q});
}
else{
cin>>x;
get_change(E[x-1].first,E[x-1].second,-1);
}
}
return 0;
}

/*
`                       4    000      4
                       44   0   0    44
x   x  y   y  x   x    44   0   0    44
x   x  y   y  x   x   4 4   0   0   4 4
 x x   y   y   x x    4 4   0   0   4 4
  x     y y     x    4  4   0   0  4  4
 x x    y y    x x   44444  0   0  44444
x   x    y    x   x     4   0   0     4
x   x    y    x   x     4    000      4
       yy
*/

再写完后可以写 P3038,这题是保证查询的两个节点直接相连,但是不保证修改的直接相连,可以尝试写。