求助,线段树合并冒出了1e8个节点
  • 板块灌水区
  • 楼主abruce
  • 当前回复6
  • 已保存回复6
  • 发布时间2021/3/18 19:42
  • 上次更新2023/11/5 01:55:11
查看原帖
求助,线段树合并冒出了1e8个节点
104324
abruce楼主2021/3/18 19:42

题目是bzoj4771,思路是这个,调了一整天了,发现是merge产生了过多节点,下面是代码。

#include<bits/stdc++.h>

using namespace std;
inline int read() {
	int __x=0,__f=1;
	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();
	}
	return __x*__f;
}
char __F[200];
inline void write(int __x) {
	if(__x<0) {
		putchar('-');
		__x=-__x;
	}
	if(__x>=10)write(__x/10);
	putchar(__x%10+'0');
}
const int maxn=1e5+5;
struct edge {
	int next,to;
} e[maxn*2];
int T,n,m,a[maxn],h[maxn],cnt,lst,rt[maxn],rt2[maxn],d[maxn],delrt,maxd,shik,sk2;
void addedge(int x,int y) {
	e[++cnt].next=h[x];
	e[cnt].to=y;
	h[x]=cnt;
}
namespace tree1 {
#define lc(x) t[x].l
#define rc(x) t[x].r
	struct tree {
		int l,r,sum;
	} t[maxn*1000];
	int tot;
	void pushup(int id) {
		t[id].sum=t[lc(id)].sum+t[rc(id)].sum;
	}
	int merge(int a,int b,int l,int r) {
		if(!a||!b)return a+b;
		int w=++tot;
		//shik++;
		if(l==r) {
			t[w].sum=t[a].sum+t[b].sum;
			return w;
		}
		int mid=(l+r)/2;
		lc(w)=merge(lc(a),lc(b),l,mid);
		rc(w)=merge(rc(a),rc(b),mid+1,r);
		pushup(w);
		return w;
	}
	void add(int &id,int l,int r,int v,int k) {
		if(!id)id=++tot;
		//cout<<l<<' '<<r<<' '<<v<<' '<<k<<'*'<<endl;
		if(l==r) {
			t[id].sum+=k;
			return;
		}
		int mid=(l+r)/2;
		v<=mid?add(lc(id),l,mid,v,k):add(rc(id),mid+1,r,v,k);
		pushup(id);
	}
	int ask(int id,int l,int r,int L,int R) {
		//cout<<id<<' '<<l<<' '<<r<<' '<<L<<' '<<R<<' '<<t[id].sum<<endl;
		if(!id)return 0;
		if(L<=l&&R>=r)return t[id].sum;
		int ans=0,mid=(l+r)/2;
		if(L<=mid)ans+=ask(lc(id),l,mid,L,R);
		if(R>mid)ans+=ask(rc(id),mid+1,r,L,R);
		return ans;
	}
	void dfscout(int id,int l,int r) {
		if(!id)return;
		cout<<id<<' '<<l<<' '<<r<<' '<<t[id].sum<<endl;
		if(l==r)return;
		int mid=(l+r)/2;
		dfscout(lc(id),l,mid),dfscout(rc(id),mid+1,r);
	}
#undef lc
#undef rc
}
namespace tree2 {
#define lc(x) t[x].l
#define rc(x) t[x].r
	struct tree {
		int l,r,v;
	} t[maxn*40];
	int tot;
	int merge(int a,int b,int l,int r) {
		if(!a||!b)return a+b;
		if(l==r) {
			tree1::add(delrt,1,n,max(t[a].v,t[b].v),-1);
			t[a].v=min(t[a].v,t[b].v);
			return a;
		}
		int mid=(l+r)/2;
		lc(a)=merge(lc(a),lc(b),l,mid);
		rc(a)=merge(rc(a),rc(b),mid+1,r);
		return a;
	}
	void add(int &id,int l,int r,int v,int k) {
		if(!id)id=++tot;
		//cout<<id<<' '<<l<<' '<<r<<' '<<v<<' '<<k<<' '<<u<<'*'<<endl;
		if(l==r) {
			t[id].v=k;
			return;
		}
		int mid=(l+r)/2;
		v<=mid?add(lc(id),l,mid,v,k):add(rc(id),mid+1,r,v,k);
	}
#undef lc
#undef rc
}
void dfs(int u) {
	//write(u),putchar('\n');
	tree2::add(rt2[u],1,n,a[u],d[u]);
	int ltt=tree1::tot;
	tree1::add(rt[u],1,n,d[u],1);
	delrt=0;
	for(register int i=h[u]; i; i=e[i].next) {
		int j=e[i].to;
		d[j]=d[u]+1;
		dfs(j);
		rt2[u]=tree2::merge(rt2[u],rt2[j],1,n);
		rt[u]=tree1::merge(rt[u],rt[j],1,n);
	}
//	puts("------");
//	cout<<u<<endl;
	rt[u]=tree1::merge(rt[u],delrt,1,n);
	if(u%300==0)cout<<tree1::tot-ltt<<' '<<shik<<' '<<u<<endl;
//	tree1::dfscout(rt[u],1,n);
}
int main() {
	int x,y;
	T=read();
	while(T--) {
		memset(rt,0,(n+1)*4);
		memset(rt2,0,(n+1)*4);
		memset(tree1::t,0,(tree1::tot+1)*sizeof(tree1::t[0]));
		memset(tree2::t,0,(tree2::tot+1)*sizeof(tree2::t[0]));
		memset(h,0,(n+1)*4);
		tree1::tot=tree2::tot=cnt=lst=0;
		n=read(),m=read();
		for(register int i=1; i<=n; i++)a[i]=read();
		for(register int i=2; i<=n; i++)x=read(),addedge(x,i);
		dfs(1);
//		for(register int i=1;i<=n;i++)puts("------"),cout<<i<<endl,tree1::dfscout(rt[i],1,n);
		for(register int i=1; i<=m; i++) {
			x=read(),y=read();
			x^=lst,y^=lst;
//			cout<<x<<' '<<y<<' ';
			lst=tree1::ask(rt[x],1,maxd,d[x],d[x]+y);
			write(lst),putchar('\n');
		}
		//exit(0);
	}
	return 0;
}
2021/3/18 19:42
加载中...