P2146 [NOI2015] 软件包管理器 ——树链剖分 线段树
题意
分析
我们认为一个点安装/不安装对应 1/0。
对于安装操作,查询目标点到根节点路径上的安装数并将路径上的点全部修改为 1 。
对于卸载操作,查询目标点子树内的 1 的个数并将子树的点全部修改为 0 。
codes:
#include<bits/stdc++.h> using namespace std; const int N=1e5+100; inline int read() { register char c=getchar();int x=0; while(!isdigit(c))c=getchar(); while(isdigit(c)){x=(x<<1)+(x<<3)+c-48;c=getchar();} return x; } int n,q,dep[N],f[N],siz[N],son[N]; int deg[N],top[N],id[N],rk[N],dfn,sta[N]; vector<int>to[N]; void go1(int u,int fa) { f[u]=fa;dep[u]=dep[fa]+1;siz[u]=1; for(int i=0;i<deg[u];++i) { int v=to[u][i]; go1(v,u); if(siz[v]>siz[son[u]])son[u]=v; siz[u]+=siz[v]; } } void go2(int u,int tp) { id[u]=++dfn;rk[dfn]=u;top[u]=tp; if(son[u])go2(son[u],tp); for(int i=0;i<deg[u];++i) { int v=to[u][i]; if(v==son[u])continue; go2(v,v); } } struct segtree { struct node { int val,tag; node(){tag=-1;} }s[N<<2]; void pushup(int i){s[i].val=s[i<<1].val+s[i<<1|1].val;} void pushtag(int i,int z,int x){s[i].val=x*z;s[i].tag=z;} void pushdown(int i,int l,int r) { if(s[i].tag==-1)return ; int mid=(l+r)>>1; pushtag(i<<1,s[i].tag,mid-l+1); pushtag(i<<1|1,s[i].tag,r-mid); s[i].tag=-1; } int que(int i,int l,int r,int x,int y) { if(l>=x && r<=y)return s[i].val; int mid=(l+r)>>1,sum=0;pushdown(i,l,r); if(x<=mid)sum+=que(i<<1,l,mid,x,y); if(y>mid)sum+=que(i<<1|1,mid+1,r,x,y); return sum; } void fix(int i,int l,int r,int x,int y,int z) { if(l>=x && r<=y){pushtag(i,z,r-l+1);return ;} int mid=(l+r)>>1;pushdown(i,l,r); if(x<=mid)fix(i<<1,l,mid,x,y,z); if(y>mid)fix(i<<1|1,mid+1,r,x,y,z); pushup(i); } int got(int x,int y){return que(1,1,n,x,y);} void cl(int x,int y,int z){fix(1,1,n,x,y,z);} }T; void init() { scanf("%d",&n); for(int i=2,x;i<=n;++i) { x=read()+1; ++deg[x]; to[x].push_back(i); } go1(1,0); go2(1,1); } int rer(int x) { int sum=0; while(top[x]!=1) { int num=dep[x]-dep[top[x]]+1-T.got(id[top[x]],id[x]); if(num==0)return sum; sum+=num; T.cl(id[top[x]],id[x],1); x=f[top[x]]; } sum+=dep[x]-dep[1]+1-T.got(id[1],id[x]); T.cl(id[1],id[x],1); return sum; } void work() { scanf("%d",&q); while(q--) { char t=getchar(); while(t>'z' || t<'a')t=getchar(); int x=read()+1; if(t=='i') { if(T.got(id[x],id[x])==1){printf("0\n");continue;} printf("%d\n",rer(x)); } else { if(T.got(id[x],id[x])==0){printf("0\n");continue;} printf("%d\n",T.got(id[x],id[x]+siz[x]-1)); T.cl(id[x],id[x]+siz[x]-1,0); } } } int main() { init(); work(); return 0; }
本文来自博客园,作者:Glowingfire,转载请注明原文链接:https://www.cnblogs.com/Glowingfire/p/18732925
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程