【bzoj4196】[NOI2015]软件包管理器

8 篇文章 0 订阅
3 篇文章 0 订阅

树剖
完全没有对链的操作,维护一个dfs序就好
这个题调了1个多小时,树链剖分写丑了。。。
要注意树剖的线段树维护的是dfs序,所以起止是1 - n而不是0 - n-1
其实也是因为从来把1当作根结点,所以偶尔把0当作根结点就容易写丑了,平常的练习还是要培养自己的码风,这样有助于比赛的时候正常的发挥.

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
//树剖的线段树维护的是dfs序,所以起止是1 - n而不是0 - n-1 
using namespace std;
const int N=100010;
int n,m,sz,qx,te;
char s[15];
int head[N],num[N],son[N],fa[N],tp[N],size[N];
struct edge{
    int u,v,next;
}e[200020];
struct seg{
    int l,r;
    int numi,numu,tag;
}tr[600010];
inline int F()
{
    register int aa,bb;register char ch;
    while(ch=getchar(),(ch<'0'||ch>'9')&&ch!='-');ch=='-'?aa=bb=0:(aa=ch-'0',bb=1);
    while(ch=getchar(),ch>='0'&&ch<='9')aa=(aa<<3)+(aa<<1)+ch-'0';return bb?aa:-aa;
}
void add(int u,int v)
{
    e[++te].u=u;
    e[te].v=v;
    e[te].next=head[u];
    head[u]=te;
}
void dfs1(int x)
{
    size[x]=1;
    int maxson=0;
    for (int i=head[x];i;i=e[i].next)
    {
        int v=e[i].v;
        if (v==fa[x])continue;
        fa[v]=x;
        dfs1(v);
        size[x]+=size[v];
        if (size[v]>maxson)son[x]=v,maxson=size[v];
    }
}
void dfs2(int x,int chain)
{
    tp[x]=chain;
    num[x]=++sz;
    if(son[x]==-1)return;
    dfs2(son[x],chain);
    for (int i=head[x];i;i=e[i].next)
    {
        int v=e[i].v;
        if (v==fa[x]||v==son[x])continue;
        dfs2(v,v);
    } 
}
void pushdown(int k)
{
    int l=tr[k].l,r=tr[k].r;
    if (tr[k].tag==-1||l==r)return;
    int mid=(l+r)>>1;
    tr[k<<1].tag=tr[k<<1|1].tag=tr[k].tag;
    if (tr[k].tag==0)
    {
        tr[k<<1].numu=mid-l+1;
        tr[k<<1|1].numu=r-mid;
        tr[k<<1].numi=tr[k<<1|1].numi=0;
    }
    else 
    {
        tr[k<<1].numi=mid-l+1;
        tr[k<<1|1].numi=r-mid;
        tr[k<<1].numu=tr[k<<1|1].numu=0;
    }
    tr[k].tag=-1;
}
void updata(int k)
{
    tr[k].numi=tr[k<<1].numi+tr[k<<1|1].numi;
    tr[k].numu=tr[k<<1].numu+tr[k<<1|1].numu;
}
void build(int k,int l,int r)
{
    tr[k].l=l,tr[k].r=r,tr[k].tag=-1;
    if (l==r)
    {
        tr[k].numi=0;
        tr[k].numu=1;
        return; 
    }
    int mid=(l+r)>>1;
    build(k<<1,l,mid);
    build(k<<1|1,mid+1,r);
    updata(k);
}
void change(int k,int x,int y,int z)
{
//  cout<<tr[k].l<<' '<<tr[k].r<<' '<<tr[k].numi<<' '<<tr[k].numu<<' '<<x<<' '<<y<<endl;
    int l=tr[k].l,r=tr[k].r;
    if (x<=l&&r<=y)
    {
        tr[k].tag=z;
        if (z)
        {
            qx+=tr[k].numu;
            tr[k].numi=r-l+1;
            tr[k].numu=0;
        }
        else 
        {
            qx+=tr[k].numi;
            tr[k].numu=r-l+1;
            tr[k].numi=0;
        }
        return;
    }
    pushdown(k);
    int mid=(l+r)>>1;
    if (x<=mid)change(k<<1,x,y,z);
    if (y>mid)change(k<<1|1,x,y,z);
    updata(k);
}
void query(int x)
{
    while(tp[x]!=0)
    {
        change(1,num[tp[x]],num[x],1);
        x=fa[tp[x]]; 
    }
    change(1,num[tp[x]],num[x],1);
    return ;
}
int main()
{
//  freopen("std.in","r",stdin);
    memset(son,-1,sizeof(son));
    int x,u,v;
    n=F();
    for (int i=1;i<n;++i)
    v=F(),add(v,i);
    fa[0]=0;
    dfs1(0);dfs2(0,0);build(1,1,n);
    m=F();
    for (int i=1;i<=m;++i)
    {
//      cout<<endl<<endl<<endl<<endl<<endl;
        scanf("%s",s);
        x=F();qx=0; 
        if (s[0]=='i')query(x);
        else change(1,num[x],num[x]+size[x]-1,0);
        printf("%d\n",qx);
    }
    return 0;
} 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值