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;
}
posted @   Glowingfire  阅读(2)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程
点击右上角即可分享
微信分享提示