3052: [wc2013]糖果公园

3052: [wc2013]糖果公园

Time Limit: 200 Sec   Memory Limit: 512 MB
Submit: 962   Solved: 464
[ Submit][ Status][ Discuss]

Description

Input

Output

Sample Input

Sample Input

Sample Output

84
131
27
84

HINT


Source

[ Submit][ Status][ Discuss]


树上莫队,,今天一天几乎都花在这上面了
首先是按照bzoj1086的方法把树分块,每个块的大小控制在N^(2/3)
对于每个询问,假设路径为(u,v)且u所在的块的编号不大于v
把所有询问操作按照u为第一关键字,v为第二关键字,时间为第三关键字排序
我们维护的信息是当前这条路径的ans(除去lca)
转移的时候,设下一次的路径是(x,y)
先暴力转移时间
然后暴力从u走到x,路径上的点的信息取反
同样地从v走到y
ans的话,,把lca的信息补上即可
为什么这样做是对的呢???
vfleaking大神讲的非常有道理
最后是时间复杂度(苟蒻也只会证明这个了。。GG)
我们把树许多个分成了N^(2/3)的块
于是块的数量就不超过N(1/3)
显然,在同一块内,你怎么跑单次的复杂度都不超过O(N^(2/3))
对于u所在的块确定是,v所在的块若在块内跑O(N^(2/3)),若要跑向右边的块,,总和是N^(2/3)*N^(1/3) = N
至于每次确定两端点的块时,时间修改的总和是O(N)  右子树跑O(N^(1/3))次,左子树也是一样
所以时间的修改是O(N^(5/3)),路径同理
这个复杂度,,强行没有N^2反正可以过


写的时候Movetime函数写残了,,好蠢啊
点取反再取回来是要特判的!!!
得从cur for 到 target才对呀!!!!
#include<iostream>
#include<cstdio>
#include<queue>
#include<vector>
#include<bitset>
#include<algorithm>
#include<cstring>
#include<map>
#include<stack>
#include<set>
#include<cmath>
#include<ext/pb_ds/priority_queue.hpp>
using namespace std;

const int maxn = 1E5 + 10;
const int Siz = 1234;
typedef long long LL;

struct Mo{
	int pos,a,b;
	Mo(int _pos = 0,int _a = 0,int _b = 0) {pos = _pos; a = _a; b = _b;}
}M[maxn];

struct Qu{
	int L,R,t,beL,beR;
	Qu(int _L = 0,int _R = 0,int _beL = 0,int _beR = 0,int _t = 0) {
		L = _L; R = _R; beL = _beL; beR = _beR; t = _t;
		if (beL > beR) swap(L,R),swap(beL,beR);
	}
	bool operator < (const Qu &b) const {
		if (beL < b.beL) return 1;
		if (beL > b.beL) return 0;
		if (beR < b.beR) return 1;
		if (beR > b.beR) return 0;
		return t < b.t;	
	}
}Q[maxn]; 

int n,m,q,cnt,Root,top,t,s[maxn],co[maxn],fa[maxn][20],
	A,B,Lca,num[maxn],c[maxn],depth[maxn],belong[maxn];
LL now,ans[maxn],va[maxn],w[maxn];
bool vis[maxn];

vector <int> v[maxn];

int getint()
{
	int ret = 0;
	char ch = getchar();
	while (ch < '0' || '9' < ch) ch = getchar();
	while ('0' <= ch && ch <= '9') ret = ret*10 + ch - '0',ch = getchar();
	return ret;
}

void dfs(int x,int from)
{
	for (int i = 1; i < 20; i++) fa[x][i] = fa[fa[x][i-1]][i-1];
	int k = top;
	for (int i = 0; i < v[x].size(); i++) {
		int to = v[x][i];
		if (to == from) continue;
		depth[to] = depth[x] + 1;
 		fa[to][0] = x;
 		dfs(to,x);
 		if (top - k >= Siz) {
			++cnt;
			while (top != k) belong[s[top--]] = cnt;
 		}
	}
	s[++top] = x;
}

void XorV(int x)
{
	if (vis[x]) {
		now -= va[num[x]]*w[co[num[x]]];
		vis[x] = 0; --co[num[x]];
	}
	else {
		++co[num[x]]; vis[x] = 1;
		now += va[num[x]]*w[co[num[x]]];
	}
}

void XorPath(int p,int q)
{
	if (depth[p] < depth[q]) swap(p,q);
	while (depth[p] > depth[q]) XorV(p),p = fa[p][0];
	if (p == q) return;
	while (p != q) {
		XorV(p); p = fa[p][0];
		XorV(q); q = fa[q][0];
	}
}

int LCA(int p,int q) 
{
	if (depth[p] < depth[q]) swap(p,q);
	int Log; for (Log = 0; depth[p] - (1<<Log) >= 1; Log++); --Log;
	for (int j = Log; j >= 0; j--)
		if (depth[p] - (1<<j) >= depth[q])
			p = fa[p][j];
	if (p == q) return p;
	for (int j = Log; j >= 0; j--)
		if (fa[p][j] != fa[q][j])
			p = fa[p][j],q = fa[q][j];
	return fa[p][0];
}

void Movetime(int cur,int target)
{
	if (cur < target) {
		for (int i = cur + 1; i <= target; i++) {
			if (!M[i].pos) continue;
			bool flag = 0; 
			if (vis[M[i].pos]) XorV(M[i].pos),flag = 1;
			num[M[i].pos] = M[i].b; 
			if (flag) XorV(M[i].pos);
		}
	}
	else {
		for (int i = cur; i > target; i--) {
			if (!M[i].pos) continue;
			bool flag = 0; 
			if (vis[M[i].pos]) XorV(M[i].pos),flag = 1;
			num[M[i].pos] = M[i].a; 
			if (flag) XorV(M[i].pos);
		}
	}
}

int main()
{
	#ifdef DMC
		freopen("DMC.txt","r",stdin);
	#endif
	
	n = getint(); m = getint(); q = getint();
	for (int i = 1; i <= m; i++) va[i] = getint();
	for (int i = 1; i <= n; i++) w[i] = getint();
	for (int i = 1; i < n; i++) {
		int x = getint(),y = getint();
		v[x].push_back(y);
		v[y].push_back(x);
	}
	for (int i = 1; i <= n; i++) num[i] = c[i] = getint();
	Root = n/2; depth[Root] = 1; dfs(Root,0); int tot = 0;
	while (top) belong[s[top--]] = cnt;
	for (int i = 1; i <= q; i++) {
		int typ = getint(),x = getint(),y = getint();
		if (typ) Q[++tot] = Qu(x,y,belong[x],belong[y],i);
		else M[i] = Mo(x,c[x],y),c[x] = y;
	}
	sort(Q + 1,Q + tot + 1);
	A = B = Lca = Root; t = 0;
	for (int i = 1; i <= tot; i++) {
		Movetime(t,Q[i].t); t = Q[i].t;
		XorPath(A,Q[i].L); A = Q[i].L;
		XorPath(B,Q[i].R); B = Q[i].R;
		Lca = LCA(A,B); XorV(Lca);
		ans[Q[i].t] = now; XorV(Lca);
	}
	for (int i = 1; i <= q; i++)
		if (ans[i])
			printf("%lld\n",ans[i]);
	return 0;
}

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值