萌新求助线段树套fhq
查看原帖
萌新求助线段树套fhq
234623
zlx517楼主2021/3/4 11:02

同一份数据,程序有时候会卡死,有时候却运行正常

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <ctime>
using namespace std;
const int maxn = 5e5 + 5,inf = 2147483647;
int n,m,tot;
int w[maxn];

int ch[maxn][2],val[maxn],pri[maxn],siz[maxn];
int pushup(int now)
{
	siz[now] = siz[ch[now][0]] + siz[ch[now][1]] + 1;
}
int new_node(int v)
{
	siz[++tot] = 1;
	val[tot] = v;
	pri[tot] = rand();
	return tot;
}
int merge(int x,int y)
{
	//cout<<x<<' '<<y<<endl;
	if(!x || !y) return x + y;
	if(pri[x] < pri[y])
	{
		//cout<<pri[x]<<' '<<pri[y]<<endl;
		ch[x][1] = merge(ch[x][1],y);
		pushup(x);
		return x;
	}
	else
	{
		//cout<<pri[x]<<' '<<pri[y]<<endl;
		ch[y][0] = merge(x,ch[y][0]);
		pushup(y);
		return y;
	}
}
void split(int now,int k,int &x,int &y)
{
	//cout<<1<<endl;
	if(!now) x = y = 0;
	else
	{
		if(val[now] <= k) x = now,split(ch[now][1],k,ch[now][1],y);
		else y = now,split(ch[now][0],k,x,ch[now][0]);
		pushup(now);
	}
}
int get_k(int now,int k)
{
	while(1)
	{
		if(k <= siz[ch[now][0]]) now = ch[now][0];
		else if(k == siz[ch[now][0]] + 1) return now;
		else k -= siz[ch[now][0]] + 1,now = ch[now][1];
	}
}
int rak(int &root,int v)
{
	int x,y;
	split(root,v - 1,x,y);
	int ans = siz[x] + 1;
	root = merge(x,y);
	//cout<<ans<<endl;
	return ans;
}
void insert(int &root,int v)
{
	int x,y;
	split(root,v,x,y);
	root = merge(merge(x,new_node(v)),y);
}
void del(int &root,int v)
{
	int x,y,z;
	split(root,v,x,z);
	split(root,v - 1,x,y);
	y = merge(ch[y][0],ch[y][1]);
	root = merge(merge(x,y),z);
}
void update(int &root,int v,int k)
{
	del(root,v);
	insert(root,k);
}
int get_pre(int &root,int v)
{
	int x,y;
	split(root,v - 1,x,y);
	int ans = val[get_k(x,siz[x])];
	root = merge(x,y);
	return ans;
}
int get_suc(int &root,int v)
{
	int x,y;
	split(root,v,x,y);
	int ans = val[get_k(y,1)];
	root = merge(x,y);
	return ans;
}

int L[maxn],R[maxn],T[maxn];
void build(int u,int l,int r)
{
	L[u] = l,R[u] = r;
	insert(T[u],-inf),insert(T[u],inf);
	//cout<<T[u];
	int mid = (l + r) / 2;
	for(int i = l; i <= r; i++) insert(T[u],w[i]);
	if(l == r) return ;
	build(u * 2,l,mid),build(u * 2 + 1,mid + 1,r);
}
int query(int u,int a,int b,int x)
{
	//cout<<L[u]<<' '<<R[u]<<' '<<a<<' '<<b<<endl;
	if(L[u] >= a && R[u] <= b)
	{
		//cout<<1;
		return rak(T[u],x) - 1;
	} 
	int mid = (L[u] + R[u]) / 2,res = 0;
	if(a <= mid) res += query(u * 2,a,b,x);
	if(b > mid) res += query(u * 2 + 1,a,b,x);
	return res;
}
void change(int u,int p,int x)
{
	update(T[u],w[p],x);
	if(L[u] == R[u]) return ;
	int mid = (L[u] + R[u]) / 2;
	if(p <= mid) change(u * 2,p,x);
	else change(u * 2 + 1,p,x);
}
int query_pre(int u,int a,int b,int x)
{
	if(L[u] >= a && R[u] <= b) return get_pre(T[u],x);
	int mid = (L[u] + R[u]) / 2,res = -inf;
	if(a <= mid) res = max(res,query_pre(u * 2,a,b,x));
	if(b > mid) res = max(res,query_pre(u * 2 + 1,a,b,x));
	return res;
}
int query_suc(int u,int a,int b,int x)
{
	if(L[u] >= a && R[u] <= b) return get_suc(T[u],x);
	int mid = (L[u] + R[u]) / 2,res = inf;
	if(a <= mid) res = min(res,query_suc(u * 2,a,b,x));
	if(b > mid) res = min(res,query_suc(u * 2 + 1,a,b,x));
	return res;
}
int main()
{
	srand((unsigned)time(NULL));
	scanf("%d%d",&n,&m);
	for(int i = 1; i <= n; i++)
	{
		scanf("%d",&w[i]);
	}
	build(1,1,n);
	for(int i = 1; i <= m; i++)
	{
		int op,a,b,x;
		scanf("%d",&op);
		if(op == 1)
		{
			scanf("%d%d%d",&a,&b,&x);
			printf("%d\n",query(1,a,b,x) + 1);
		}
		else if(op == 2)
		{
			scanf("%d%d%d",&a,&b,&x);
			int l = 0,r = 1e8;
			while(l < r)
			{
				int mid = (l + r + 1) / 2;
				if(query(1,a,b,mid) + 1 <= x) l = mid;
				else r = mid - 1;
			}
			printf("%d\n",r);
		}
		else if(op == 3)
		{
			scanf("%d%d",&a,&x);
			change(1,a,x);
			w[a] = x;
		}
		else if(op == 4)
		{
			scanf("%d%d%d",&a,&b,&x);
			printf("%d\n",query_pre(1,a,b,x));
		}
		else
		{
			scanf("%d%d%d",&a,&b,&x);
			printf("%d\n",query_suc(1,a,b,x));
		}
	} 
	return 0;
}
2021/3/4 11:02
加载中...