【BZOJ3757】苹果树
【BZOJ3232】圈地游戏

【BZOJ3052】【WC2013】糖果公园

Zarxdy34 posted @ 2016年3月06日 21:01 in BZOJ with tags 树上莫队 , 581 阅读

  带修改树上莫队。取每块大小为\({n^{\frac{2}{3}}}\),依然对询问排序,第一关键字为左端点所在块编号,第二关键字为右端点所在块编号,第三关键字为该操作的编号。

  暴力查询+修改,时间复杂度\(O({n^{\frac{5}{3}}})\),由于我的代码自带大常数特效,所以跑了114s。

 

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

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

struct Query
{
	int x,y,ct,xblock,yblock,id;
}Q[maxn];

struct Modification
{
	int x,y,lasty;
}M[maxn];

int temp[maxn];
int head[maxn],next[maxn<<1],E[maxn<<1],Ecnt;
LL V[maxn],W[maxn],C[maxn];
int belong[maxn],Bcnt;
int dep[maxn],fa[maxn][20];
int n,m,q,Qs,Ms,B;
LL ans[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 stack[maxn],top;
void DFS(int x,int father,int depth)
{
	dep[x]=depth;
	fa[x][0]=father;
	for (int l=0;fa[fa[x][l]][l];l++) fa[x][l+1]=fa[fa[x][l]][l];
	int bottom=top;
	for (int i=head[x];i;i=next[i]) if (E[i]!=father)
	{
		DFS(E[i],x,depth+1);
		if (top-bottom>=B)
		{
			Bcnt++;
			while (top>bottom) belong[stack[top--]]=Bcnt;
		}
	}
	stack[++top]=x;
}

void Init()
{
	read(n),read(m),read(q);
	B=pow(n,2.0/3.0);
	for (int i=1;i<=m;i++) read(V[i]);
	for (int i=1;i<=n;i++) read(W[i]);
	for (int i=1,x,y;i<n;i++) read(x),read(y),Add_Edge(x,y);
	for (int i=1;i<=n;i++) read(C[i]);
	for (int i=1;i<=q;i++)
	{
		int type;
		read(type);
		if (type==0) ++Ms,read(M[Ms].x),read(M[Ms].y);
		else ++Qs,read(Q[Qs].x),read(Q[Qs].y),Q[Qs].ct=Ms,Q[Qs].id=Qs;
	}
	DFS(1,0,1);
	while (top) belong[stack[top--]]=Bcnt;
	for (int i=1;i<=Qs;i++)
	{
		if (belong[Q[i].x]>belong[Q[i].y]) swap(Q[i].x,Q[i].y);
		Q[i].xblock=belong[Q[i].x],Q[i].yblock=belong[Q[i].y];
	}
	for (int i=1;i<=n;i++) temp[i]=C[i];
	for (int i=1;i<=Ms;i++) M[i].lasty=temp[M[i].x],temp[M[i].x]=M[i].y;
}

bool cmp(const Query &a,const Query &b) {return a.xblock<b.xblock || (a.xblock==b.xblock && (a.yblock<b.yblock || (a.yblock==b.yblock && a.ct<b.ct)));}

int vis[maxn],c[maxn];
LL res;

int LCA(int u,int v)
{
	if (dep[u]<dep[v]) swap(u,v);
	int dis=dep[u]-dep[v],l=0;
	while (dis)
	{
		if (dis&1) u=fa[u][l];
		dis>>=1;l++;
	}
	l=0;
	while (fa[u][l]!=fa[v][l]) l++;
	while (l>=0)
	{
		if (fa[u][l]!=fa[v][l]) u=fa[u][l],v=fa[v][l];
		l--;
	}
	return (u!=v)?fa[u][0]:u;
}

void Update(int u,int v)
{
	v=fa[v][0];
	while (u!=v)
	{
		if (!vis[u])
		{
			res+=V[C[u]]*W[++c[C[u]]];
			vis[u]=1;
		}
		else
		{
			res-=V[C[u]]*W[c[C[u]]--];
			vis[u]=0;
		}
		u=fa[u][0];
	}
}

void Solve()
{
	sort(Q+1,Q+1+Qs,cmp);
	int u=1,v=1,ctr=0;
	for (int i=1;i<=Qs;i++)
	{
		int nu=Q[i].x,nv=Q[i].y,nctr=Q[i].ct;
		int lca=LCA(u,nu);
		Update(u,lca);Update(nu,lca);
		lca=LCA(v,nv);
		Update(v,lca);Update(nv,lca);
		u=nu;v=nv;
		lca=LCA(u,v);
		Update(lca,lca);
		while (ctr>nctr)
		{
			C[M[ctr].x]=M[ctr].lasty;
			if (vis[M[ctr].x]) res+=W[++c[M[ctr].lasty]]*V[M[ctr].lasty]-W[c[M[ctr].y]--]*V[M[ctr].y]; 
			ctr--;
		}
		while (ctr<nctr)
		{
			++ctr;
			C[M[ctr].x]=M[ctr].y;
			if (vis[M[ctr].x]) res+=W[++c[M[ctr].y]]*V[M[ctr].y]-W[c[M[ctr].lasty]--]*V[M[ctr].lasty];
		}
		ans[Q[i].id]=res;
		Update(lca,lca);
	}
	for (int i=1;i<=Qs;i++) printf("%lld\n",ans[i]);
}

int main()
{
	Init();
	Solve();
	return 0;
}

登录 *


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