萌新树上莫队TLE求助
查看原帖
萌新树上莫队TLE求助
309320
懵逼小蒟蒻楼主2024/6/20 12:55

AC[1,3],TLE[4,10]。

正确性应该没有问题,写了对拍,小数据拍不出来错误。

对于第四个点,下载下来在本地测大约10s能跑完,推测是因为常数过大寄了(应该没有假吧……)

调了好久,想不明白哪里有问题,有没有dalao可以帮我看看!

#include<bits/stdc++.h>
#define ll long long 
using namespace std;
const int N = 200005;
inline int read(){
	int s = 0;char ch = getchar();
	while(ch<'0'||ch>'9')ch = getchar();
	while(ch>='0'&&ch<='9'){s = (s<<1)+(s<<3)+ch-'0';ch = getchar();}
	return s;
}
int n,m,q,cnt[N],ect = 1,hd[N],ck[N],lid[N],khi[N],fa[N],dep[N],kct,s;
int topf[N],sz[N],son[N];
struct E{
	int v,nt;
}e[2*N];
void add(int u,int v){
	e[ect].v = v;
	e[ect].nt = hd[u];
	hd[u] = ect++;
}
bool vis[N];
//树剖的第一个dfs,同时求括号序 
void dfs(int p,int fn){
	fa[p] = fn;
	dep[p] = dep[fn]+1;
	sz[p] = 1;
	khi[++kct] = p;
	lid[p] = kct;
	for(int i = hd[p];i;i = e[i].nt){
		if(e[i].v==fn)continue;
		dfs(e[i].v,p);
		sz[p]+=sz[e[i].v];
		if(sz[son[p]]<sz[e[i].v])son[p] = e[i].v;
	}
	khi[++kct] = p;
}
//树剖的dfs2 
void dfs2(int p,int ntop){
	topf[p] = ntop;
	if(!son[p])return;
	dfs2(son[p],ntop);
	for(int i = hd[p];i;i = e[i].nt){
		if(e[i].v==fa[p]||e[i].v==son[p])continue;
		dfs2(e[i].v,e[i].v);
	}
}
ll v[N],w[N],oa[N];
struct Q{
	int u,v,id,qid,l,r;
}qr[N];
struct C{
	int p,k;
}cg[N];
//莫队排序的cmp(不保证正确性的奇偶排序优化) 
bool cmp(Q a,Q b){
	if(a.l/s==b.l/s){
		if(a.r/s==b.r/s){
			if((a.r/s)&1)return a.id>b.id;
			return a.id<b.id;
		}
		if((a.l/s)&1)return a.r>b.r;
		return a.r<b.r;
	}
	return a.l<b.l;
}
ll ans;
int l = 1,r = 0,nq = 0;
//下面传的是树上节点的编号 
void del(int p){
	p = ck[p];
	ans-=w[cnt[p]--]*v[p];
}
void add(int p){
	p = ck[p];
	ans+=w[++cnt[p]]*v[p];
}
void Cg(int p){
	p = khi[p];
	if(vis[p])del(p);
	else add(p);
	vis[p] = !vis[p];
}
void change(int cid){
	int p = cg[cid].p;
	if(vis[p]){
		del(p);
		swap(ck[p],cg[cid].k);
		add(p);
	}else{
		swap(ck[p],cg[cid].k);
	}
}
//树剖lca 
int lca(int u,int v){
	while(topf[u]!=topf[v]){
		if(dep[topf[u]]<dep[topf[v]])swap(u,v);
		u = fa[topf[u]];
	}
	if(dep[u]<dep[v])return u;
	return v;
}
int main(){
//	freopen("P4074_4.in","r",stdin);
//	freopen("dt.out","r",stdin);
//	freopen("zj.out","w",stdout);
	n = read();m = read();q = read();
	for(int i = 1;i<=m;i++)v[i] = read();
	for(int i = 1;i<=n;i++)w[i] = read();
	int uu,vv;
	for(int i = 1;i<n;i++){
		uu = read();vv = read();
		add(uu,vv);add(vv,uu);
	}
	dfs(1,0);dfs2(1,1);
	for(int i = 1;i<=n;i++)ck[i] = read();
	int cgct = 0,qrct = 0,op;
	for(int i = 1;i<=q;i++){
		op = read();
		if(op==0){
			cg[++cgct].p = read();
			cg[cgct].k = read();
			continue;
		}
		qr[++qrct].u = uu = read();
		qr[qrct].v = vv = read();
		if(lid[uu]>lid[vv]){
			swap(qr[qrct].u,qr[qrct].v);
			swap(uu,vv);
		}
		qr[qrct].id = qrct;
		qr[qrct].qid = cgct;
		qr[qrct].l = lid[uu];
		qr[qrct].r = lid[vv];
	}
	s = pow(n,2.0/3);
	q = qrct;
	int qrq,qrl,qrr;
	for(int i = 1;i<=q;i++){
		qrl = qr[i].l;qrr = qr[i].r;qrq = qr[i].qid;
		while(nq<qrq)change(++nq);
		while(nq>qrq)change(nq--);
		while(r<qrr)Cg(++r);
		while(l>qrl)Cg(--l);
		while(r>qrr)Cg(r--);
		while(l<qrl)Cg(l++);
		int nl = lca(qr[i].u,qr[i].v);
		if(nl!=qr[i].u&&nl!=qr[i].v)add(nl);
		if(qr[i].u!=nl)add(qr[i].u);
		oa[qr[i].id] = ans;
		if(nl!=qr[i].u&&nl!=qr[i].v)del(nl);
		if(qr[i].u!=nl)del(qr[i].u);
	}
	for(int i = 1;i<=q;i++){
		printf("%lld\n",oa[i]);
	}
	return 0;
}
2024/6/20 12:55
加载中...