您的位置:首页 > 其它

bzoj4196(树链剖分)

2016-07-25 11:49 267 查看
不难,但有一些细节

像这种代码量稍微大一些的题,代码比较密集,就要注意

a=a+b;是不是打成

#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<iostream>
#define debug(x) cout<<#x<<"="<<x<<endl
using namespace std;
const int N=400019;

int to
,pre
,head
,tot;//edge
int dep
,fa
,size
,son
,top
;//树链剖分
int id
,l
,r
,n;//segment tree
struct aa
{
int l,r,sum,set;
}a[N*4];
void addedge(int x,int y) {to[++tot]=y;pre[tot]=head[x];head[x]=tot;}
void dfs1(int u,int depth)
{
dep[u]=depth;
int max_size=0;size[u]=1;
for (int i=head[u];i;i=pre[i])
{
dfs1(to[i],depth+1);
size[u]+=size[to[i]];
if(size[to[i]]>max_size) max_size=size[to[i]],son[u]=to[i];
}
}
void dfs2(int u,int anc)
{
top[u]=anc;
l[u]=id[u]=++tot;
if (son[u]) dfs2(son[u],anc);
for (int i=head[u];i;i=pre[i])
if (son[u]!=to[i]) dfs2(to[i],to[i]);
r[u]=tot;
}
void build(int i,int l,int r)
{
a[i].l=l;a[i].r=r;
if (l==r) return ;
int mid=(l+r)>>1;
build(i<<1,l,mid);
build(i<<1|1,mid+1,r);
}
void up(int i)
{
a[i].sum=0;
if (a[i<<1].l) a[i].sum+=a[i<<1].sum;
if (a[i<<1|1].l) a[i].sum+=a[i<<1|1].sum;//这里刚开始就把=给丢了
}
void down(int i)
{
if (a[i].set)
{
a[i].set=0;
a[i<<1].set=a[i<<1|1].set=1;
if (a[i].sum)
a[i<<1].sum=a[i<<1].r-a[i<<1].l+1,
a[i<<1|1].sum=a[i<<1|1].r-a[i<<1|1].l+1;//这里刚开始直接写成了<span style="font-family: Arial, Helvetica, sans-serif;">a[i<<1|1].r-a[i<<1|1].l+1,没有赋值的情况,然而编译器是不会报错的</span>
<span style="white-space:pre"> </span>//这就要注意不要压行那么严重,注意有没有把赋值或return语句直接写成了一个表达式的情况
else a[i<<1].sum=a[i<<1|1].sum=0;
}
}
int find(int i,int l,int r)
{
down(i);
if (a[i].l==l&&a[i].r==r) return a[i].sum;
if (a[i].l==a[i].r)return 0;
int mid=(a[i].l+a[i].r)>>1;
if (mid>=r) return find(i<<1,l,r);
if (mid<l) return find(i<<1|1,l,r);
return find(i<<1,l,mid)+find(i<<1|1,mid+1,r);
}
void sett(int i,int l,int r,int k)
{
if (a[i].l==l&&a[i].r==r)
{
a[i].set=1;
a[i].sum=(a[i].r-a[i].l+1)*k;
return;
}
if (a[i].l==a[i].r) return;
int mid=(a[i].l+a[i].r)>>1;
if (mid>=r) sett(i<<1,l,r,k);
else if (mid<l) sett(i<<1|1,l,r,k);
else sett(i<<1,l,mid,k),sett(i<<1|1,mid+1,r,k);
up(i);
}
void install(int x)
{
int ans=0,y=x;
while (x!=-1)//把根结点的父亲设为-1,因为如果有根结点的一个轻儿子,那么top就是这个儿子,而他的父亲就是0,x==0了,就会退出,最后没有处理根节点的情况,写题的时候,这样的情况需要多斟酌一下,既然感觉可能有错,就应该好好考虑,不放过每一个可能出错的地方
{
ans+=find(1,id[top[x]],id[x]);
x=fa[top[x]];
}
printf("%d\n",dep[y]-ans);
x=y;
while (x!=-1)
{
sett(1,id[top[x]],id[x],1);
x=fa[top[x]];
}
}
void uninstall(int x)
{
int ans=find(1,l[x],r[x]);
printf("%d\n",ans);
sett(1,l[x],r[x],0);
}
int main()
{
scanf("%d",&n);
fa[0]=-1;
for (int i=1;i<n;i++)
{
scanf("%d",&fa[i]);
addedge(fa[i],i);
}
tot=0;
dfs1(0,1);
dfs2(0,0);
build(1,1,tot);
int q,x; char c[20];
scanf("%d",&q);
while (q--)
{
scanf("%s%d",c,&x);
if (c[0]=='i') install(x);
else uninstall(x);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: