您的位置:首页 > 其它

bzoj4196[Noi2015]软件包管理器

2016-01-05 20:14 309 查看
树链剖分,徒手玩操作

很直接很裸的做就可以了,写了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
;
int last
,ne=0;
int ls[N*4],rs[N*4],w[N*4],la[N*4],siz[N*4];
int fa
,son
,dep
,top
,dfn
,en
,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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  树链剖分