bzoj4196[Noi2015]软件包管理器

树链剖分,徒手玩操作

很直接很裸的做就可以了,写了1h然后我觉得肯定要调很久的时候,直接过样例然后1A = =

/**************************************************************
    Problem: 4196
    User: BPM136
    Language: C++
    Result: Accepted
    Time:7132 ms
    Memory:13316 kb
****************************************************************/
 
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<bitset>
#define LL long long
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define efo(i,x) for(int i=last[x];i!=0;i=e[i].next)
using namespace std;
#define N 100005
struct edge
{
    int y,next;
}e[N];
int last[N],ne=0;
int ls[N*4],rs[N*4],w[N*4],la[N*4],siz[N*4];
int fa[N],son[N],dep[N],top[N],dfn[N],en[N],nu=0;
int n,m,root=1,ans=0;
 
void dfs1(int x,int de,int pre)
{
    dep[x]=de;fa[x]=pre;siz[x]=1;
    int ma=0,f=0;
    efo(i,x)
    {
        dfs1(e[i].y,de+1,x);
        siz[x]+=siz[e[i].y];
        if(siz[e[i].y]>ma)
        {
            ma=siz[e[i].y];
            f=e[i].y;
        }
    }
    son[x]=f;
}
 
void dfs2(int x,int t)
{
    dfn[x]=++nu;top[x]=t;
    if(son[x])dfs2(son[x],t);
    efo(i,x)
    if(e[i].y!=son[x])
    dfs2(e[i].y,e[i].y);
    en[x]=nu;
}
 
void pushup(int k)
{
    ls[k]=ls[k<<1];
    rs[k]=rs[k<<1|1];
    w[k]=la[k]=0;
}   
 
void buildsegtree(int k,int l,int r)
{
    if(l==r)
    {
        rs[k]=ls[k]=l;
        w[k]=0;la[k]=-1;
        return;
    }
    int mid=(l+r)>>1;
    buildsegtree(k<<1,l,mid);buildsegtree(k<<1|1,mid+1,r);
    pushup(k);
}
 
void prework()
{
    nu=0;dfs1(root,1,0);dfs2(root,root);
    buildsegtree(1,1,nu);
}
 
void pushlazy(int k)
{
    if(la[k]==0)
    {
        w[k<<1]=w[k<<1|1]=0;
        la[k<<1]=la[k<<1|1]=0;
    }
    if(la[k]==1)
    {
        w[k<<1]=rs[k<<1]-ls[k<<1]+1;
        w[k<<1|1]=rs[k<<1|1]-ls[k<<1|1]+1;
        la[k<<1]=la[k<<1|1]=1;
    }
    la[k]=-1;
}
 
int change1seg(int k,int l,int r)
{
    if(ls[k]==l&&rs[k]==r)
    {
        int num=r-l+1;
        int anss=num-w[k];
        la[k]=1;w[k]=num;
        return anss;
    }
    int mid=(ls[k]+rs[k])>>1,flag=0;
    if(la[k]!=-1)pushlazy(k);
    if(r<=mid)flag=change1seg(k<<1,l,r);
    else
    {
        if(l>mid)flag=change1seg(k<<1|1,l,r);
        else flag=change1seg(k<<1,l,mid)+change1seg(k<<1|1,mid+1,r);
    }
    w[k]=w[k<<1]+w[k<<1|1];
    return flag;
}
 
void change1(int k)
{
    if(k==0)return;
    int t=top[k];
    if(t==0)ans+=change1seg(1,dfn[k],dfn[k]);
    else ans+=change1seg(1,dfn[t],dfn[k]);
    change1(fa[t]);
}
 
int change0seg(int k,int l,int r)
{
    if(ls[k]==l&&rs[k]==r)
    {
        int num=r-l+1;
        int anss=w[k];
        w[k]=0;la[k]=0;
        return anss;
    }
    int mid=(ls[k]+rs[k])>>1;int flag=0;
    if(la[k]!=-1)pushlazy(k);
    if(r<=mid)flag=change0seg(k<<1,l,r);
    else
    {
        if(l>mid)flag=change0seg(k<<1|1,l,r);
        else flag=change0seg(k<<1,l,mid)+change0seg(k<<1|1,mid+1,r);
    }
    w[k]=w[k<<1]+w[k<<1|1];
    return flag;
}
 
void change0(int k)
{
    ans=change0seg(1,dfn[k],en[k]);
}
 
void add(int x,int y)
{
    e[++ne].y=y;e[ne].next=last[x];last[x]=ne;
}
 
int main()
{
    scanf("%d",&n);
    fo(i,1,n-1)
    {
        int x;scanf("%d",&x);
        fa[i+1]=x+1;
        add(x+1,i+1);
    }
    prework();
    int t;scanf("%d",&t);
    while(t--)
    {
        char s[20];int ch;ans=0;
        scanf("%s%d",s,&ch);ch++;
        if(s[0]=='i')change1(ch);
        else change0(ch);
        printf("%d\n",ans);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值