树链剖分同时记录子树区间
对于install操作,直接爬上根结点,进行更新查询操作
对于unstall操作,直接询问子树区间,更新子树区间
#include #include #include #include #include #include #include #include #include #include //#pragma comment(linker, "/STACK:1024000000,1024000000"); using namespace std; #define INF 0x3f3f3f3f #define maxn 300005 int fir[maxn],nex[maxn],v[maxn],e_max; int son[maxn],fa[maxn],top[maxn],siz[maxn],deep[maxn],tot; int in[maxn],out[maxn]; int sum[2*maxn],tag[2*maxn]; void init_() { memset(fir,-1,sizeof fir); memset(son,-1,sizeof son); memset(in,0,sizeof in); memset(out,0,sizeof out); e_max=0; tot=1; } void add_edge(int s,int t) { int e=e_max++; v[e]=t; nex[e]=fir[s]; fir[s]=e; } void dfs1(int k,int pre,int d) { deep[k]=d; siz[k]=1; fa[k]=pre; for(int i=fir[k];~i;i=nex[i]) { int e=v[i]; if(e!=pre) { dfs1(e,k,d+1); siz[k]+=siz[e]; if(son[k]==-1||siz[son[k]]>1; init(l,mid,k<<1); init(mid+1,r,k<<1|1); sum[k]=sum[k<<1]+sum[k<<1|1]; } void pushdown(int l,int r,int k) { if(tag[k]==-1) return ; int mid=l+r>>1; tag[k<<1]=tag[k<<1|1]=tag[k]; if(tag[k]) sum[k<<1]=mid-l+1,sum[k<<1|1]=r-mid; else sum[k<<1]=sum[k<<1|1]=0; tag[k]=-1; } void update(int d,int s,int t,int l,int r,int k) { if(s==l&&r==t) { tag[k]=d; if(d) sum[k]=r-l+1; else sum[k]=0; return ; } pushdown(l,r,k); int mid=l+r>>1; if(t<=mid) update(d,s,t,l,mid,k<<1); else if(s>mid) update(d,s,t,mid+1,r,k<<1|1); else { update(d,s,mid,l,mid,k<<1); update(d,mid+1,t,mid+1,r,k<<1|1); } sum[k]=sum[k<<1]+sum[k<<1|1]; } int query(int s,int t,int l,int r,int k) { if(s==l&&r==t) { return sum[k]; } pushdown(l,r,k); int mid=l+r>>1; if(t<=mid) return query(s,t,l,mid,k<<1); else if(s>mid) return query(s,t,mid+1,r,k<<1|1); else return query(s,mid,l,mid,k<<1)+query(mid+1,t,mid+1,r,k<<1|1); } int Query(int s,int t) { int ans=0; int f1=top[s],f2=top[t]; while(f1!=f2) { if(deep[f1]deep[t]) swap(s,t); ans+=query(in[s],in[t],1,tot-1,1); update(0,in[s],in[t],1,tot-1,1); return ans; } int main() { int n; while(scanf("%d",&n)!=EOF) { init_(); for(int i=1;i