鏈剖——BZOJ3631/Luogu3258 [JLOI2014]松鼠的新家


題面:BZOJ3631 Luogu3258
簡要題面:每次修改樹上一條鏈的值(+1),最后詢問每個點的值
裸的樹剖,內套區間修改線段樹
我本來還以為這題碼量可以稍微少一點(因為一開始線段樹上都為0),可惜的是我其他還記錄着東西
所以代碼還是光榮地快上百行了
最后輸出時候要注意一點,因為每個中轉點(就是鏈的端點)都被多算了一次(第一個和最后一個除外),因為中轉點各屬於兩條不同的鏈
再加上最后一個點最后到的時候沒有糖果,所以最后除了第一個點其他所有點在輸出時-1

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<cstdlib>
#include<string>
#include<ctime>
#include<queue>
#include<climits>
using namespace std;
int a[300001];
int n,nedge=0,p[600001],nex[600001],head[600001];
int fa[300001],deep[300001],s[300001],son[300001],top[300001];
int sx[300001],xs[300001],ne=0;
int lt[1200001],rt[1200001],t[1200001],add[1200001];
inline void addedge(int a,int b){p[++nedge]=b;nex[nedge]=head[a];head[a]=nedge;}
inline void dfs(int x,int Fa,int dep){
fa[x]=Fa;deep[x]=dep;s[x]=1;
for(int k=head[x];k;k=nex[k]){
if(p[k]==Fa)continue;
dfs(p[k],x,dep+1);s[x]+=s[p[k]];
if(!son[x]||s[p[k]]>s[son[x]])son[x]=p[k];
}
}
inline void dfss(int x,int bh){
top[x]=bh;sx[x]=++ne;xs[sx[x]]=x;
if(!son[x])return;
dfss(son[x],bh);
for(int k=head[x];k;k=nex[k])if(p[k]!=son[x]&&p[k]!=fa[x])dfss(p[k],p[k]);
}
inline void clean(int nod){
if(add[nod]==0)return;
if(lt[nod]!=rt[nod]){
t[nod*2]=t[nod*2]+add[nod]*(rt[nod*2]-lt[nod*2]+1);
add[nod*2]+=add[nod];
t[nod*2+1]=t[nod*2+1]+add[nod]*(rt[nod*2+1]-lt[nod*2+1]+1);
add[nod*2+1]+=add[nod];
}
add[nod]=0;
}
inline void build(int l,int r,int nod){
lt[nod]=l;rt[nod]=r;
if(l==r){t[nod]=0;return;}
int mid=l+r>>1;
build(l,mid,nod*2);build(mid+1,r,nod*2+1);
t[nod]=t[nod*2]+t[nod*2+1];
}
inline void xg(int i,int j,int nod){
clean(nod);
if(lt[nod]>=i&&rt[nod]<=j){t[nod]+=rt[nod]-lt[nod]+1;add[nod]=1;return;}
int mid=lt[nod]+rt[nod]>>1;
if(i<=mid)xg(i,j,nod*2);
if(j>mid)xg(i,j,nod*2+1);
t[nod]=t[nod*2]+t[nod*2+1];
}
inline int ssum(int i,int j,int nod){
clean(nod);
if(lt[nod]>=i&&rt[nod]<=j)return t[nod];
int mid=lt[nod]+rt[nod]>>1,ans=0;
if(i<=mid)ans+=ssum(i,j,nod*2);
if(j>mid)ans+=ssum(i,j,nod*2+1);
return ans;
}
inline int fsum(int x,int y){
int fx=top[x],fy=top[y],ans=0;
while(fx!=fy){
if(deep[fx]<deep[fy])swap(fx,fy),swap(x,y);
ans+=ssum(sx[fx],sx[x],1);
x=fa[fx];fx=top[x];
}
if(deep[x]>deep[y])swap(x,y);
ans+=ssum(sx[x],sx[y],1);
return ans;
}
inline void fxg(int x,int y){
int fx=top[x],fy=top[y];
while(fx!=fy){
if(deep[fx]<deep[fy])swap(fx,fy),swap(x,y);
xg(sx[fx],sx[x],1);
x=fa[fx];fx=top[x];
}
if(deep[x]>deep[y])swap(x,y);
xg(sx[x],sx[y],1);
}
int main()
{
scanf("%d",&n);a[0]=1;
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
for(int i=1;i<n;i++){
int x,y;scanf("%d%d",&x,&y);
addedge(x,y);addedge(y,x);
}
dfs(1,0,1);dfss(1,1);build(1,n,1);
for(int i=2;i<=n;i++)fxg(a[i-1],a[i]);
for(int i=1;i<=n;i++)if(a[1]!=i)printf("%d\n",ssum(sx[i],sx[i],1)-1);
else printf("%d\n",ssum(sx[i],sx[i],1));
return 0;
}

注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com