[bzoj 4196][NOI 2015]软件包管理器
大概算是一道模板题吧?
就是细节有点多
罗列一下:
- 如果习惯从1开始搞树的编号的话,处理输入进来的那个依赖关系在加边的时候两个都要+1,体现在代码就是i要从2枚举到n,然后输入进来的那个数要+1
- 这道题的线段树的打法也有所不同,因为只有两种状态,也就是已安装和未安装,我这里是用1和0来表示的,所以lazy标记就不能打成0了,我的代码中是用-1来表示的,注意要判这个东西(当然你也可以用1和2表示这两种状态)
- 线段树的修改也要改一下,+=得改成=(显然?)
这些细节都处理好后就是一个树剖模板了
#include <cstdio> #include <cstring> #define ll int #define inf 1<<30 #define il inline il ll max(ll x,ll y){return x>y?x:y;} il ll min(ll x,ll y){return x<y?x:y;} il ll abs(ll x){return x>0?x:-x;} il void swap(ll &x,ll &y){ll t=x;x=y;y=t;} il void read(ll &x){ x=0;ll f=1;char c=getchar(); while(c<'0'||c>'9'){if(c=='-')f=-f;c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} x*=f; } il void print(ll x){if(x<0)putchar('-');x=abs(x);if(x>9)print(x/10);putchar(x%10+'0');} il void writeln(ll x){if(x<0)putchar('-');x=abs(x);print(x);putchar('\n');} il void write(ll x){if(x<0)putchar('-');x=abs(x);print(x);putchar(' ');} using namespace std; /*===================Header Template=====================*/ #define N 100010 struct edge{ll to,next;}e[N<<2]; struct tree{ll l,r,sum,lazy;}t[N<<2]; ll cnt,head[N],sz,n,m,a[N]; ll pos[N],fa[N],dep[N],siz[N],top[N]; void insert(ll u,ll v){ e[++cnt].next=head[u];e[cnt].to=v;head[u]=cnt; e[++cnt].next=head[v];e[cnt].to=u;head[v]=cnt; } void dfs1(ll x){ siz[x]=1; for(ll i=head[x];i;i=e[i].next){ if(fa[x]==e[i].to)continue; dep[e[i].to]=dep[x]+1; fa[e[i].to]=x; dfs1(e[i].to); siz[x]+=siz[e[i].to]; } } void dfs2(ll x,ll topf){ ll k=0; pos[x]=++sz; top[x]=topf; for(ll i=head[x];i;i=e[i].next){ if(dep[e[i].to]>dep[x]&&siz[e[i].to]>siz[k]) k=e[i].to; } if(k==0)return; dfs2(k,topf); for(ll i=head[x];i;i=e[i].next){ if(dep[e[i].to]>dep[x]&&k!=e[i].to){ dfs2(e[i].to,e[i].to); } } } void pushdown(ll ln,ll rn,ll rt){ if(t[rt].lazy!=-1){ ll &x=t[rt].lazy; t[rt<<1].sum=ln*x; t[rt<<1|1].sum=rn*x; t[rt<<1].lazy=x; t[rt<<1|1].lazy=x; x=-1; } } void build(ll l,ll r,ll rt){ t[rt].l=l;t[rt].r=r;t[rt].lazy=-1; if(l==r)return; ll mid=(l+r)>>1; build(l,mid,rt<<1); build(mid+1,r,rt<<1|1); } void upd(ll L,ll R,ll c,ll rt){ ll l=t[rt].l,r=t[rt].r,mid=(l+r)>>1; if(L<=l&&r<=R){t[rt].sum=(r-l+1)*c;t[rt].lazy=c;return;} pushdown(mid-l+1,r-mid,rt); if(L<=mid)upd(L,R,c,rt<<1); if(R>mid)upd(L,R,c,rt<<1|1); t[rt].sum=t[rt<<1].sum+t[rt<<1|1].sum; } ll query(ll L,ll R,ll rt){ ll l=t[rt].l,r=t[rt].r,mid=(l+r)>>1,ans=0; if(L<=l&&r<=R)return t[rt].sum; pushdown(mid-l+1,r-mid,rt); if(L<=mid)ans+=query(L,R,rt<<1); if(R>mid)ans+=query(L,R,rt<<1|1); return ans; } void A(ll x,ll y){ while(top[x]!=top[y]){ if(dep[top[x]]<dep[top[y]])swap(x,y); upd(pos[top[x]],pos[x],0,1); x=fa[top[x]]; } if(pos[x]>pos[y])swap(x,y); upd(pos[x],pos[y],0,1); } ll Q(ll x,ll y){ ll sum=0; while(top[x]!=top[y]){ if(dep[top[x]]<dep[top[y]])swap(x,y); sum+=query(pos[top[x]],pos[x],1); x=fa[top[x]]; } if(pos[x]>pos[y])swap(x,y); sum+=query(pos[x],pos[y],1); return sum; } int main(){ read(n); for(ll i=2;i<=n;i++){ ll x;read(x);x++; insert(i,x); } dfs1(1);dfs2(1,1); build(1,n,1); upd(1,n,1,1); read(m); while(m--){ char ch[10];ll x; scanf("%s%d",ch,&x);x++; if(ch[0]=='i'){writeln(Q(x,1));A(x,1);} if(ch[0]=='u'){ writeln(siz[x]-query(pos[x],pos[x]+siz[x]-1,1)); upd(pos[x],pos[x]+siz[x]-1,1,1); } } return 0; }
转载请注明出处:https://www.cnblogs.com/henry-1202/p/9152370.html