【BZOJ1040】骑士
【BZOJ2440】完全平方数

【BZOJ4196】软件包管理器

Zarxdy34 posted @ 2015年11月26日 21:04 in BZOJ with tags 树链剖分 , 395 阅读

    裸的树链剖分,就是再加一个修改子树的操作,子树在线段树里是连续的。

 

 

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=100010;

struct Segment_Tree
{
	int sum[maxn<<2];
	int tag_same[maxn<<2];
	int tag_clear[maxn<<2];
	int _l,_r;
	int n;
	
	#define ls (o<<1)
	#define rs ((o<<1)|1)
	#define mid ((l+r)>>1)

	void Mark_Clear(int o)
	{
		sum[o]=0;
		tag_same[o]=0;
		tag_clear[o]=1;
	}

	void Mark_Same(int o,int l,int r)
	{
		sum[o]=r-l+1;
		tag_clear[o]=0;
		tag_same[o]=1;
	}

	void Push_Down(int o,int l,int r)
	{
		if (l==r) return;
		if (tag_clear[o])
		{
			Mark_Clear(ls);
			Mark_Clear(rs);
			tag_clear[o]=0;
		}
		if (tag_same[o])
		{
			Mark_Same(ls,l,mid);
			Mark_Same(rs,mid+1,r);
			tag_same[o]=0;
		}
	}

	void Update(int o) {sum[o]=sum[ls]+sum[rs];}

	void Change_Same(int o,int l,int r)
	{
		if (_l<=l && r<=_r) {Mark_Same(o,l,r);return;}
		Push_Down(o,l,r);
		if (_l<=mid) Change_Same(ls,l,mid);
		if (_r>mid)  Change_Same(rs,mid+1,r);
		Update(o);
	}

	void Change_Clear(int o,int l,int r)
	{
		if (_l<=l && r<=_r) {Mark_Clear(o);return;}
		Push_Down(o,l,r);
		if (_l<=mid) Change_Clear(ls,l,mid);
		if (_r>mid)  Change_Clear(rs,mid+1,r);
		Update(o);
	}

	int Query(int o,int l,int r)
	{
		if (_l<=l && r<=_r) return sum[o];
		Push_Down(o,l,r);
		int res=0;
		if (_l<=mid) res+=Query(ls,l,mid);
		if (_r>mid)  res+=Query(rs,mid+1,r);
		Update(o);
		return res;
	}

	int Sum() {return sum[1];}
	void Change_Same(int _a,int _b) {_l=_a;_r=_b;Change_Same(1,1,n);}
	void Change_Clear(int _a,int _b) {_l=_a;_r=_b;Change_Clear(1,1,n);}
	#undef ls
	#undef rs
	#undef mid
}ST;

struct Tree
{
	int head[maxn],next[maxn<<1],E[maxn<<1],Ecnt;
	int fa[maxn],dep[maxn];
	int top[maxn],wson[maxn];
	int id[maxn],ids;
	int l[maxn],r[maxn];

	void Add_Edge(int x,int y) {next[++Ecnt]=head[x];head[x]=Ecnt;E[Ecnt]=y;next[++Ecnt]=head[y];head[y]=Ecnt;E[Ecnt]=x;}

	int DFS1(int x,int father,int depth)
	{
		int sons=0,maxsons=0;
		fa[x]=father;dep[x]=depth;
		for (int i=head[x];i;i=next[i]) if (E[i]!=father)
		{
			int tsons=DFS1(E[i],x,depth+1);
			sons+=tsons;
			if (tsons>maxsons) maxsons=tsons,wson[x]=E[i];
		}
		return sons+1;
	}

	void DFS2(int x,int is_wson)
	{
		id[x]=++ids;
		l[x]=ids;
		if (is_wson) top[x]=top[fa[x]];else top[x]=x;
		if (wson[x]) DFS2(wson[x],1);
		for (int i=head[x];i;i=next[i]) if (E[i]!=fa[x] && E[i]!=wson[x]) DFS2(E[i],0);
		r[x]=ids;
	}

	void Build(int n)
	{
		(void)DFS1(0,0,1);
		DFS2(0,1);
		ST.n=n;
	}

	int Install(int x)
	{
		int pre=ST.Sum();
		while (x!=0) ST.Change_Same(id[top[x]],id[x]),x=fa[top[x]];
		ST.Change_Same(id[0],id[0]);
		return ST.Sum()-pre;
	}

	int Unistall(int x)
	{
		int pre=ST.Sum();
		ST.Change_Clear(l[x],r[x]);
		return pre-ST.Sum();
	}
}T;

void read(int &x) {char ch;while ((ch=getchar())<'0' || ch>'9');x=ch-'0';while ((ch=getchar())>='0' && ch<='9') x=x*10+ch-'0';}

char ctr[20];
int n,q;

int main()
{
	read(n);
	for (int i=1,y;i<n;i++) read(y),T.Add_Edge(i,y);
	T.Build(n);
	read(q);
	for (int i=1,x;i<=q;i++)
	{
		scanf("%s",ctr);
		read(x);
		if (ctr[0]=='i') printf("%d\n",T.Install(x));
		if (ctr[0]=='u') printf("%d\n",T.Unistall(x));
	}
	return 0;
}

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter