zoukankan      html  css  js  c++  java
  • [bzoj 4196][NOI 2015]软件包管理器

    大概算是一道模板题吧?

    就是细节有点多

    罗列一下:

    1. 如果习惯从1开始搞树的编号的话,处理输入进来的那个依赖关系在加边的时候两个都要+1,体现在代码就是i要从2枚举到n,然后输入进来的那个数要+1
    2. 这道题的线段树的打法也有所不同,因为只有两种状态,也就是已安装和未安装,我这里是用1和0来表示的,所以lazy标记就不能打成0了,我的代码中是用-1来表示的,注意要判这个东西(当然你也可以用1和2表示这两种状态)
    3. 线段树的修改也要改一下,+=得改成=(显然?)

    这些细节都处理好后就是一个树剖模板了

    #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('
    ');}
    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

  • 相关阅读:
    需求调研-用户访谈
    kettle监控销售人员当月每天任务完成率_20161107周一
    MySQL学习_计算用户支付方式占比_20161104
    MySQL 数据底部出现总计字样 第二种办法 纵向合并 20161103
    MySQL 单笔订单满6个及以上产品且金额>=300赠送优惠券_20161103
    MySQL学习_查看各仓库产品的销售情况_20161102
    MySQL与EXCEL sum sumif sumifs 函数结合_品牌汇总_20161101
    MySQL_活动期间单笔订单最高的且满600元 判别是重激活客户还是10月注册客户_20161031
    MySQL活动期间订单满600元并且在活动日期之前超过30天没有下过单_20161030
    MySQL活动期间制定月份注册用户下单情况_20161029
  • 原文地址:https://www.cnblogs.com/henry-1202/p/9152374.html
Copyright © 2011-2022 走看看