https://www.luogu.org/problem/show?pid=3379#sub
树剖lca
代码
博客我晚上再写;
先把要写的代码放好;
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=5e5+5;
struct di{int fa,size,top,deep;}d[N];
struct cs{int to,nxt;}a[N*2];
int head[N],ll;
int n,m,s,x,y;
void init(int x,int y){
a[++ll].to=y;
a[ll].nxt=head[x];
head[x]=ll;
}
void dfs1(int x,int deep,int y){
d[x].deep=deep; d[x].fa=y; d[x].size=1;
for(int k=head[x];k;k=a[k].nxt)
if(a[k].to!=y)dfs1(a[k].to,deep+1,x),d[x].size+=d[a[k].to].size;
}
void dfs2(int x,int now,int y){
if(now==-1)now=x;
d[x].top=now;
int ma=0;
for(int k=head[x];k;k=a[k].nxt)
if(a[k].to!=y)
if(ma==0||d[a[k].to].size>d[ma].size)ma=a[k].to;
for(int k=head[x];k;k=a[k].nxt)
if(a[k].to!=y)
if(a[k].to==ma)dfs2(a[k].to,now,x);else dfs2(a[k].to,-1,x);
}
int lca(int x,int y){
while(d[x].top!=d[y].top)
if(d[d[x].top].deep>d[d[y].top].deep)
x=d[d[x].top].fa;else y=d[d[y].top].fa;
if(d[x].deep>d[y].deep)return y;return x;
}
int main()
{
scanf("%d%d%d",&n,&m,&s);
for(int i=1;i<n;i++){
scanf("%d%d",&x,&y);
init(x,y); init(y,x);
}
dfs1(s,1,-6);
dfs2(s,-1,-6);
while(m--){
scanf("%d%d",&x,&y);
printf("%d\n",lca(x,y));
}
}
https://daniu.luogu.org/problem/show?pid=2590
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=3e4+5;
struct di{int fa,size,top,deep,v,to,to2;}d[N];
struct cs{int to,nxt;}a[N*2];
struct tree{int l,r,sum,ma;}T[200000];
int head[N],ll,time;
int n,m,s,x,y;
char c[20];
void init(int x,int y){
a[++ll].to=y;
a[ll].nxt=head[x];
head[x]=ll;
}
void dfs1(int x,int deep,int y){
d[x].deep=deep; d[x].fa=y; d[x].size=1;
for(int k=head[x];k;k=a[k].nxt)
if(a[k].to!=y)dfs1(a[k].to,deep+1,x),d[x].size+=d[a[k].to].size;
}
void dfs2(int x,int now,int y){
if(now==-1)now=x;
d[x].top=now; d[x].to=++time; d[time].to2=x;
int ma=0;
for(int k=head[x];k;k=a[k].nxt)
if(a[k].to!=y)
if(ma==0||d[a[k].to].size>d[ma].size)ma=a[k].to;
if(ma)dfs2(ma,now,x);
for(int k=head[x];k;k=a[k].nxt)
if(a[k].to!=y&&a[k].to!=ma)dfs2(a[k].to,-1,x);
}
void up(int x){
int y=x*2,z=x*2+1;
T[x].ma=max(T[y].ma,T[z].ma);
T[x].sum=T[y].sum+T[z].sum;
}
void maketree(int l,int r,int num){
T[num].l=l; T[num].r=r;
if(l==r){T[num].ma=T[num].sum=d[d[l].to2].v;return;}
int mid=l+r>>1;
maketree(l,mid ,num*2 );
maketree(mid+1,r,num*2+1);
up(num);
}
void change(int num,int x,int y){
if(T[num].l==T[num].r){T[num].ma=T[num].sum=y;return;}
if(T[num*2].r>=x)change(num*2,x,y);else change(num*2+1,x,y);
up(num);
}
int find1(int num,int x,int y){
if(x<=T[num].l&&T[num].r<=y)return T[num].ma;
int ans=-1e9;
if(T[num*2 ].r>=x)ans=max(ans,find1(num*2 ,x,y));
if(T[num*2+1].l<=y)ans=max(ans,find1(num*2+1,x,y));
return ans;
}
int findmax(int x,int y){
int ans=-1e9;
while(d[x].top!=d[y].top)
if(d[d[x].top].deep>d[d[y].top].deep){
ans=max(ans,find1(1,d[d[x].top].to,d[x].to));
x=d[d[x].top].fa;
}else{
ans=max(ans,find1(1,d[d[y].top].to,d[y].to));
y=d[d[y].top].fa;
}
if(d[x].deep>d[y].deep)swap(x,y);
ans=max(ans,find1(1,d[x].to,d[y].to));
return ans;
}
int find2(int num,int x,int y){
if(x<=T[num].l&&T[num].r<=y)return T[num].sum;
int ans=0;
if(T[num*2 ].r>=x)ans+=find2(num*2 ,x,y);
if(T[num*2+1].l<=y)ans+=find2(num*2+1,x,y);
return ans;
}
int findsum(int x,int y){
int ans=0;
while(d[x].top!=d[y].top)
if(d[d[x].top].deep>d[d[y].top].deep){
ans+=find2(1,d[d[x].top].to,d[x].to);
x=d[d[x].top].fa;
}else{
ans+=find2(1,d[d[y].top].to,d[y].to);
y=d[d[y].top].fa;
}
if(d[x].deep>d[y].deep)swap(x,y);
ans+=find2(1,d[x].to,d[y].to);
return ans;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<n;i++){
scanf("%d%d",&x,&y);
init(x,y); init(y,x);
}
dfs1(1,1,-6);
dfs2(1,-1,-6);
for(int i=1;i<=n;i++)scanf("%d",&d[i].v);
maketree(1,n,1);
scanf("%d",&m);
while(m--){
scanf("%s%d%d",c,&x,&y);
if(c[1]=='H')change(1,d[x].to,y);else
if(c[1]=='M')printf("%d\n",findmax(x,y));else
if(c[1]=='S')printf("%d\n",findsum(x,y));
}
}
https://daniu.luogu.org/problem/show?pid=2486
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e5+5;
struct di{int fa,size,top,deep,v,to,to2;}d[N];
struct cs{int to,nxt;}a[N*2];
struct tree{int l,r,x,y,v,tag;}T[270000];
int head[N],ll,time;
int n,m,x,y,z,xx,yy;
char c;
void init(int x,int y){
a[++ll].nxt=head[x];
a[ll].to=y;
head[x]=ll;
}
void dfs1(int x,int y,int deep){
d[x].deep=deep; d[x].fa=y; d[x].size=1;
for(int k=head[x];k;k=a[k].nxt)
if(a[k].to!=y)dfs1(a[k].to,x,deep+1),d[x].size+=d[a[k].to].size;
}
void dfs2(int x,int y,int now){
if(now==-1)now=x; d[x].top=now;
d[x].to=++time; d[time].to2=x;
int ma=0;
for(int k=head[x];k;k=a[k].nxt)
if(a[k].to!=y&&(ma==0||d[ma].size<d[a[k].to].size))ma=a[k].to;
if(ma)dfs2(ma,x,now);
for(int k=head[x];k;k=a[k].nxt)
if(a[k].to!=y&&a[k].to!=ma)dfs2(a[k].to,x,-1);
}
void up(int x){
int y=x*2,z=x*2+1;
T[x].x=T[y].x; T[x].y=T[z].y;
T[x].v=T[y].v+T[z].v-int(T[y].y==T[z].x);
}
void down(int num){
if(!T[num].tag)return;
int x=num*2,y=num*2+1;
if(T[num].l==T[num].r){T[num].tag=0;return;}
T[x].tag=T[y].tag=T[x].x=T[y].x=T[x].y=T[y].y=T[num].tag;
T[x].v=T[y].v=1; T[num].tag=0;
}
void maketree(int l,int r,int num){
T[num].l=l; T[num].r=r;
if(l==r){T[num].x=T[num].y=d[d[l].to2].v; T[num].v=1;return;}
int mid=l+r>>1;
maketree(l,mid ,num*2 );
maketree(mid+1,r,num*2+1);
up(num);
}
void change(int num,int x,int y,int z){
down(num);
if(x<=T[num].l&&T[num].r<=y){T[num].x=T[num].y=T[num].tag=z;T[num].v=1;return;}
if(T[num*2 ].r>=x)change(num*2 ,x,y,z);
if(T[num*2+1].l<=y)change(num*2+1,x,y,z);
up(num);
}
void work(int x,int y,int z){
while(d[x].top!=d[y].top)
if(d[d[x].top].deep>d[d[y].top].deep){
change(1,d[d[x].top].to,d[x].to,z);
x=d[d[x].top].fa;
}else{
change(1,d[d[y].top].to,d[y].to,z);
y=d[d[y].top].fa;
}
if(d[x].deep>d[y].deep)swap(x,y);
change(1,d[x].to,d[y].to,z);
}
int outit(int num,int x,int y){
down(num);
if(T[num].l==x&&T[num].r<=y)xx=T[num].x;
if(T[num].r==y&&T[num].l>=x)yy=T[num].y;
if(x<=T[num].l&&T[num].r<=y)return T[num].v;
int ans=0;
if(T[num*2 ].r>=x)ans+=outit(num*2 ,x,y);
if(T[num*2+1].l<=y)ans+=outit(num*2+1,x,y);
if(T[num*2].r>=x&&T[num*2+1].l<=y&&T[num*2].y==T[num*2+1].x)ans--;
return ans;
}
int find(int x,int y){
int ans=0,x1=0,x2=0;
while(d[x].top!=d[y].top)
if(d[d[x].top].deep>d[d[y].top].deep){
ans+=outit(1,d[d[x].top].to,d[x].to);
if(x1==yy)ans--;
x=d[d[x].top].fa;
x1=xx;
}else{
ans+=outit(1,d[d[y].top].to,d[y].to);
if(x2==yy)ans--;
y=d[d[y].top].fa;
x2=xx;
}
if(d[x].deep>d[y].deep)swap(x,y),swap(x1,x2);
ans+=outit(1,d[x].to,d[y].to);
if(x1==xx)ans--;if(x2==yy)ans--;
return ans;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%d",&d[i].v);
for(int i=1;i<n;i++)scanf("%d%d",&x,&y),init(x,y),init(y,x);
dfs1(1,-6,1);
dfs2(1,-6,-1);
maketree(1,n,1);
while(m--){
cin>>c;
if(c=='C'){
scanf("%d%d%d",&x,&y,&z);
work(x,y,z);
}else{
scanf("%d%d",&x,&y);
printf("%d\n",find(x,y));
}
}
}
模版
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e5+5;
struct dian{int x,y;}c[N];
struct di{int fa,size,top,deep,v,to,to2;}d[N];
struct cs{int to,nxt;}a[N*2];
struct tree{int l,r,v,tag;}T[270000];
int head[N],ll,time;
int n,m,x,y,z,mo,s;
void init(int x,int y){
a[++ll].to=y;
a[ll].nxt=head[x];
head[x]=ll;
}
void dfs1(int x,int deep,int y){
d[x].deep=deep; d[x].fa=y; d[x].size=1;
for(int k=head[x];k;k=a[k].nxt)
if(a[k].to!=y)dfs1(a[k].to,deep+1,x),d[x].size+=d[a[k].to].size;
}
void dfs2(int x,int now,int y){
if(now==-1)now=x;
d[x].top=now; d[x].to=++time; d[time].to2=x;
c[x].x=time;
int ma=0;
for(int k=head[x];k;k=a[k].nxt)
if(a[k].to!=y)
if(ma==0||d[a[k].to].size>d[ma].size)ma=a[k].to;
if(ma)dfs2(ma,now,x);
for(int k=head[x];k;k=a[k].nxt)
if(a[k].to!=y&&a[k].to!=ma)dfs2(a[k].to,-1,x);
c[x].y=time;
}
void up(int x){T[x].v=(T[x*2].v+T[x*2+1].v)%mo;}
void down(int num){
if(T[num].tag==0)return;
if(T[num].l==T[num].r){T[num].tag=0;return;}
int x=num*2,y=num*2+1;
T[x].v=(T[x].v+T[num].tag*(T[x].r-T[x].l+1))%mo;
T[y].v=(T[y].v+T[num].tag*(T[y].r-T[y].l+1))%mo;
T[x].tag=(T[x].tag+T[num].tag)%mo;
T[y].tag=(T[y].tag+T[num].tag)%mo;
T[num].tag=0;
}
void maketree(int l,int r,int num){
T[num].l=l; T[num].r=r;
if(l==r){T[num].v=d[d[l].to2].v%mo;return;}
int mid=l+r>>1;
maketree(l,mid ,num*2 );
maketree(mid+1,r,num*2+1);
up(num);
}
void change(int num,int x,int y,int z){
down(num);
if(x<=T[num].l&&T[num].r<=y){T[num].v=(T[num].v+z*(T[num].r-T[num].l+1))%mo;T[num].tag=z;return;}
if(T[num*2 ].r>=x)change(num*2 ,x,y,z);
if(T[num*2+1].l<=y)change(num*2+1,x,y,z);
up(num);
}
void work1(int x,int y,int z){
while(d[x].top!=d[y].top)
if(d[d[x].top].deep>d[d[y].top].deep){
change(1,d[d[x].top].to,d[x].to,z);
x=d[d[x].top].fa;
}else{
change(1,d[d[y].top].to,d[y].to,z);
y=d[d[y].top].fa;
}
if(d[x].deep>d[y].deep)swap(x,y);
change(1,d[x].to,d[y].to,z);
}
int find2(int num,int x,int y){
down(num);
if(x<=T[num].l&&T[num].r<=y)return T[num].v;
int ans=0;
if(T[num*2 ].r>=x)ans+=find2(num*2 ,x,y);
if(T[num*2+1].l<=y)ans+=find2(num*2+1,x,y);
return ans%mo;
}
int work2(int x,int y){
int ans=0;
while(d[x].top!=d[y].top)
if(d[d[x].top].deep>d[d[y].top].deep){
ans+=find2(1,d[d[x].top].to,d[x].to);
x=d[d[x].top].fa; ans%=mo;
}else{
ans+=find2(1,d[d[y].top].to,d[y].to);
y=d[d[y].top].fa;ans%=mo;
}
if(d[x].deep>d[y].deep)swap(x,y);
ans+=find2(1,d[x].to,d[y].to);
return ans%mo;
}
int main()
{
scanf("%d%d%d%d",&n,&m,&s,&mo);
for(int i=1;i<=n;i++)scanf("%d",&d[i].v);
for(int i=1;i<n;i++){
scanf("%d%d",&x,&y);
init(x,y);init(y,x);
}
dfs1(s,1,-1);
dfs2(s,-1,-1);
maketree(1,n,1);
while(m--){
int k;scanf("%d",&k);
if(k==1){
scanf("%d%d%d",&x,&y,&z);
work1(x,y,z%mo);
}else
if(k==2){
scanf("%d%d",&x,&y);
printf("%d\n",work2(x,y));
}else
if(k==3){
scanf("%d%d",&x,&z);
y=c[x].y;
x=c[x].x;
change(1,x,y,z);
}else{
scanf("%d",&x);
y=c[x].y;
x=c[x].x;
printf("%d\n",find2(1,x,y));
}
}
}
https://www.luogu.org/problem/show?pid=2146#sub
P2146 软件包管理器
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e5+5;
struct dian{int x,y;}c[N];
struct di{int fa,size,top,deep,v,to,to2;}d[N];
struct cs{int to,nxt;}a[N*2];
struct tree{int l,r,v,tag;}T[270000];
int head[N],ll,time;
int n,m,x,y,z,mo,s;
char cc[10];
void init(int x,int y){
a[++ll].to=y;
a[ll].nxt=head[x];
head[x]=ll;
}
void dfs1(int x,int y,int deep){
d[x].deep=deep; d[x].fa=y; d[x].size=1;
for(int k=head[x];k;k=a[k].nxt)
if(a[k].to!=y)dfs1(a[k].to,x,deep+1),d[x].size+=d[a[k].to].size;
}
void dfs2(int x,int y,int now){
if(now==-1)now=x; d[x].top=now;
d[x].to=++time; d[time].to2=x;
int ma=0; c[x].x=time;
for(int k=head[x];k;k=a[k].nxt)
if(a[k].to!=y&&(ma==0||d[ma].size<d[a[k].to].size))ma=a[k].to;
if(ma)dfs2(ma,x,now);
for(int k=head[x];k;k=a[k].nxt)
if(a[k].to!=y&&a[k].to!=ma)dfs2(a[k].to,x,-1);
c[x].y=time;
}
void up(int x){T[x].v=T[x*2].v+T[x*2+1].v;}
void down(int num){
if(T[num].tag==-1)return;
if(T[num].l==T[num].r){T[num].tag=-1;return;}
int x=num*2,y=num*2+1;
T[x].v=T[num].tag*(T[x].r-T[x].l+1);
T[y].v=T[num].tag*(T[y].r-T[y].l+1);
T[x].tag=T[y].tag=T[num].tag;
T[num].tag=-1;
}
void maketree(int l,int r,int num){
T[num].l=l; T[num].r=r; T[num].tag=-1;
if(l==r){T[num].v=1;return;}
int mid=l+r>>1;
maketree(l,mid ,num*2 );
maketree(mid+1,r,num*2+1);
up(num);
}
void change(int num,int x,int y,int z){
down(num);
if(x<=T[num].l&&T[num].r<=y){T[num].v=z*(T[num].r-T[num].l+1);T[num].tag=z;return;}
if(T[num*2 ].r>=x)change(num*2 ,x,y,z);
if(T[num*2+1].l<=y)change(num*2+1,x,y,z);
up(num);
}
int outit(int num,int x,int y){
down(num);
// cout<<T[num].l<<' '<<T[num].r<<' '<<T[num].v<<' '<<endl;
if(x<=T[num].l&&T[num].r<=y)return T[num].v;
int ans=0;
if(T[num*2 ].r>=x)ans+=outit(num*2 ,x,y);
if(T[num*2+1].l<=y)ans+=outit(num*2+1,x,y);
return ans;
}
int work1(int x){
int ans=0,y=x;
while(d[x].top!=0){
ans+=outit(1,d[d[x].top].to,d[x].to);
change(1,d[d[x].top].to,d[x].to,0);
x=d[d[x].top].fa;
}ans+=outit(1,d[0].to,d[x].to);
// cout<<d[0].to<<' '<<d[x].to<<endl;
// cout<<outit(1,d[0].to,d[x].to)<<endl;
change(1,d[0].to,d[x].to,0);
return ans;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<n;i++){
scanf("%d",&x);
init(x,i);init(i,x);
}
dfs1(0,-6,1);
dfs2(0,-6,-1);
maketree(0,n-1,1);
// for(int i=1;i<=100;i++)if(T[i].v)cout<<T[i].l<<' '<<T[i].r<<' '<<T[i].v<<endl;
for(int i=0;i<n;i++)c[i].x--,c[i].y--,d[i].to--;
scanf("%d",&m);
while(m--){
scanf("%s%d",cc,&x);
if(cc[0]=='i')printf("%d\n",work1(x));else {
printf("%d\n",d[x].size-outit(1,c[x].x,c[x].y));
change(1,c[x].x,c[x].y,1);
}
}
}