点分树全MLE,求帮助
查看原帖
点分树全MLE,求帮助
51569
wgyhm楼主2021/8/26 19:38

rt,调了一个下午+半个晚上。

自认为最可能挂的地方时 vector 的调用。

但是样例、讨论区的 hack 数据和第一个点本机测都过了,- 依然全部MLE。。。

谢谢帮忙看的大佬们。

#include<bits/stdc++.h>
#define maxn 100005
#define rg register
#define ll long long
#define put() putchar('\n')
using namespace std;
inline void read(int &x){
	int f=1;x=0;char c=getchar();
	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
	while (c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}
	x*=f;
}
int deep[maxn],lg[maxn],w[maxn];
int n,m;
int head=1,h[maxn],fa[maxn];
struct yyy{
    int to,z;
    inline void add(int x,int y){
    	to=y;z=h[x];h[x]=head;
	}
}a[maxn*2];
namespace LCA{
    int fa[maxn][21];
    inline void dfs(int x,int pre){
    	rg int i;deep[x]=deep[pre]+1;fa[x][0]=pre;
    	for (i=1;i<=lg[deep[x]];i++) fa[x][i]=fa[fa[x][i-1]][i-1];
    	for (i=h[x];i;i=a[i].z) if (a[i].to^pre) dfs(a[i].to,x);
	}
    inline void init(void){
    	rg int i;
    	for (i=2;i<=n;i++) lg[i]=lg[i/2]+1;
    	dfs(1,0);
	}
	inline int lca(int x,int y){
		rg int i;
		if (deep[x]<deep[y]) swap(x,y);
		while (deep[x]>deep[y]) x=fa[x][lg[deep[x]-deep[y]]];
		if (x==y) return x;
		for (i=lg[deep[x]];i>=0;i--) if (fa[x][i]^fa[y][i]) x=fa[x][i],y=fa[y][i];
		return fa[x][0];
	}
	inline int getdis(int x,int y){
		return deep[x]+deep[y]-2*deep[lca(x,y)];
	}
}//倍增LCA
struct BIT{
	#define lowbit(x) ((x)&(-x))
	vector<int>f;int len;
	inline void init(int size){f.resize(size);len=f.size()-1;}
	inline void add(int x,int y){rg int i;for (i=x+1;i<=len;i+=lowbit(i)) f[i]+=y;}
	inline int query(int x){rg int i,sum=0;for (i=min(x+1,len);i;i-=lowbit(i)) sum+=f[i];return sum;}
}t[maxn][2];
int Max[maxn],size[maxn],root,vis[maxn];
int sum;
inline int getroot(int x,int pre){
	rg int i;size[x]=1;Max[x]=0;
	for (i=h[x];i;i=a[i].z)
	    if (a[i].to!=pre&&!vis[a[i].to]){
	    	getroot(a[i].to,x);
	    	size[x]+=size[a[i].to];
	    	Max[x]=max(Max[x],size[a[i].to]);
		}
	Max[x]=max(Max[x],sum-size[x]);
	if (!root||Max[root]>Max[x]) root=x;
}//找根
inline void solve(int x){
	rg int i;vis[x]=1;
	t[x][0].init(sum+3);
	t[x][1].init(sum+3);//printf("%d ",sum);
	for (i=h[x];i;i=a[i].z)
	    if (!vis[a[i].to]){
	    	root=0;sum=size[a[i].to];getroot(a[i].to,0);
	    	fa[root]=x;solve(root);
		}
}//建点分树
inline void Update(int x,int w){
	rg int i;
	for (i=x;i;i=fa[i]) t[i][0].add(LCA::getdis(x,i),w);
	for (i=x;fa[i];i=fa[i]) t[i][1].add(LCA::getdis(x,fa[i]),w);
}//更新
signed main(){
//	freopen("P6329_1.in","r",stdin);
//	freopen("1.out","w",stdout);
	rg int i,x,y,op,ans=0;
	read(n);read(m);
	for (i=1;i<=n;i++) read(w[i]);
	for (i=1;i<n;i++) {
		read(x);read(y);
		a[++head].add(x,y);
		a[++head].add(y,x);
	}
	LCA::init();
	sum=n;
	getroot(1,0);
	solve(root);
	for (i=1;i<=n;i++) Update(i,w[i]);
	while (m--){
		read(op);read(x);read(y);
		x^=ans;y^=ans;
		if (op==1) Update(x,y-w[x]),w[x]=y;
		else {
			ans=t[x][0].query(y);
			for (i=x;fa[i];i=fa[i]) {
				int dis=LCA::getdis(x,fa[i]);
				if (dis<=y) ans+=t[fa[i]][0].query(y-dis)-t[i][1].query(y-dis);
			}
			printf("%d\n",ans);
		}
	}
	return 0;
}
2021/8/26 19:38
加载中...