过了,但求为什么这么慢
查看原帖
过了,但求为什么这么慢
1076971
anke2017楼主2024/11/8 10:21

我写的是线段树套 FHQ-treap,并用 vector 动态分配空间。


#include<bits/stdc++.h>

using namespace std;

struct no_rotate_treap
{
	int root=0;
	int tmp_root1,tmp_root2;
	vector<int> size;
	vector<int> num;
	vector<int> pri;
	vector<int> lson;
	vector<int> rson;
	int cnt=0;
	inline void init()
	{
		cnt=root=0;
		size.clear();size.emplace_back(0);
		num.clear();num.emplace_back(0);
		pri.clear();pri.emplace_back(0);
		lson.clear();lson.emplace_back(0);
		rson.clear();rson.emplace_back(0);
	}
	inline void update(int now)
	{
		size[now]=size[lson[now]]+size[rson[now]]+1;
	}
	inline int add(int val)
	{
		cnt++;
		pri.emplace_back(rand());
		size.emplace_back(1);
		num.emplace_back(val);
		lson.emplace_back(0);
		rson.emplace_back(0);
		return cnt;
	}
	void split(int now,int the_val,int &l,int &r)
	{
		if(!now)
		{
			l=r=0;
			return;
		}
		if(num[now]<=the_val)
		{
			l=now;
			split(rson[now],the_val,rson[now],r);
		}
		else
		{
			r=now;
			split(lson[now],the_val,l,lson[now]);
		}
		update(now);
	}
	int merge(int l,int r)
	{
		if(l&&r)
		{
			if(pri[l]<pri[r])
			{
				lson[r]=merge(l,lson[r]);
				update(r);
				return r;
			}
			else
			{
				rson[l]=merge(rson[l],r);
				update(l);
				return l;
			}
		}
		else return l+r;
	}
	__inline void insert(int x)
	{
		static int t;t=add(x);
		split(root,x,tmp_root1,tmp_root2);
		t=merge(tmp_root1,t);
		root=merge(t,tmp_root2);
	}
	__inline void erase(int x)
	{
		split(root,x,tmp_root1,tmp_root2);
		static int t;
		split(tmp_root1,x-1,tmp_root1,t);
		tmp_root1=merge(tmp_root1,lson[t]);
		tmp_root2=merge(rson[t],tmp_root2);
		root=merge(tmp_root1,tmp_root2);
	}
	__inline int rank(int x)
	{
		split(root,x-1,tmp_root1,tmp_root2);
		static int ans;ans=size[tmp_root1];
		root=merge(tmp_root1,tmp_root2);
		return ans;
	}
	int kth(int now,int k)
	{
		if(now==0)return -2147483647;
		if(size[lson[now]]>=k)return kth(lson[now],k);
		else if(size[lson[now]]+1==k)return num[now];
		else return kth(rson[now],k-size[lson[now]]-1);
	}
	__inline int find_last(int x)
	{
		split(root,x-1,tmp_root1,tmp_root2);
		static int ans;ans=kth(tmp_root1,size[tmp_root1]);
		root=merge(tmp_root1,tmp_root2);
		return ans;
	}
	__inline int find_next(int x)
	{
		split(root,x,tmp_root1,tmp_root2);
		static int ans;ans=kth(tmp_root2,1);
		if(ans==-2147483647)ans=2147483647;
		root=merge(tmp_root1,tmp_root2);
		return ans;
	}
	void print(int now)
	{
		if(!now)return;
		print(lson[now]);
		printf("num=%d,val=%d,pri=%d,size=%d,lson=%d,rson=%d\n",now,num[now],pri[now],size[now],lson[now],rson[now]);
		print(rson[now]);
	}
};//FHQ-treap

const int segment_maxn=(5e4+10)*4;

struct Segment_tree
{
	int n[segment_maxn];
	no_rotate_treap tree[segment_maxn];
	inline int lson(int n){return n<<1;}
	inline int rson(int n){return (n<<1)|1;}
	void btree(int a,int l,int r)
	{
		tree[a].init();
		for(int i=l;i<=r;i++)tree[a].insert(n[i]);
    	if(l==r)return;
    	int mid=(l+r)>>1;
    	btree(lson(a),l,mid);
    	btree(rson(a),mid+1,r);
	}
	inline void change(int a,int l,int r,int num,int x)
	{
		tree[a].erase(n[num]);tree[a].insert(x);
    	if(l==r)return;
    	int mid=(l+r)>>1;
    	if(num<=mid)change(lson(a),l,mid,num,x);
    	else change(rson(a),mid+1,r,num,x);
	}
	int ask_rank(int a,int l,int r,int lft,int rgt,int num)
	{
		if(lft<=l&&r<=rgt)return tree[a].rank(num);
		int mid=(l+r)>>1;
		int k=0;
		if(lft<=mid)k+=ask_rank(lson(a),l,mid,lft,rgt,num);
		if(mid<rgt)k+=ask_rank(rson(a),mid+1,r,lft,rgt,num);
		return k;
	}
	int ask_last(int a,int l,int r,int lft,int rgt,int num)
	{
		if(lft<=l&&r<=rgt)return tree[a].find_last(num);
		int mid=(l+r)>>1;
		int k=-2147483647;
		if(lft<=mid)k=max(k,ask_last(lson(a),l,mid,lft,rgt,num));
		if(mid<rgt)k=max(k,ask_last(rson(a),mid+1,r,lft,rgt,num));
		return k;
	}
	int ask_next(int a,int l,int r,int lft,int rgt,int num)
	{
		if(lft<=l&&r<=rgt)return tree[a].find_next(num);
		int mid=(l+r)>>1;
		int k=2147483647;
		if(lft<=mid)k=min(k,ask_next(lson(a),l,mid,lft,rgt,num));
		if(rgt>mid)k=min(k,ask_next(rson(a),mid+1,r,lft,rgt,num));
		return k;
	}
	__inline void btree(int r)
	{
		btree(1,1,r);
	}
	__inline void changeit(int maxa,int x,int add)
	{
		change(1,1,maxa,x,add);
		n[x]=add;
	}
	__inline int ask_rank(int maxa,int l,int r,int k)
	{
		return ask_rank(1,1,maxa,l,r,k)+1;
	}
	__inline int ask_last(int maxa,int l,int r,int k)
	{
		return ask_last(1,1,maxa,l,r,k);
	}
	__inline int ask_next(int maxa,int l,int r,int k)
	{
		return ask_next(1,1,maxa,l,r,k);
	}
	__inline int ask_kth(int maxa,int l,int r,int k)
	{
		static int ll,rr,mid;ll=tree[1].kth(tree[1].root,k)-1,rr=tree[1].kth(tree[1].root,maxa)+1;
		while(ll<rr-1)
		{
			mid=(ll+rr)>>1;
			//printf("mid=%d,num=%d,k=%d\n",mid,ask_rank(maxa,l,r,mid),k);
			if(ask_rank(maxa,l,r,mid)<=k)ll=mid;
			else rr=mid;
		}
		return ll;
	}
};//segment_tree
Segment_tree tree;

int main()
{
	//freopen("P3380_9.in","r",stdin);
	//freopen("P3380_9.out","w",stdout);
	ios::sync_with_stdio(false);cin.tie(0);
	int n,m;cin>>n>>m;
	for(int i=1;i<=n;i++)cin>>tree.n[i];
	tree.btree(n);
	for(int i=1;i<=m;i++)
	{
		int t1,t2,t3,t4;cin>>t1>>t2;
		switch(t1)
		{
			case 1:cin>>t3>>t4;cout<<tree.ask_rank(n,t2,t3,t4)<<'\n';break;
			case 2:cin>>t3>>t4;cout<<tree.ask_kth(n,t2,t3,t4)<<'\n';break;
			case 3:cin>>t3;tree.changeit(n,t2,t3);break;
			case 4:cin>>t3>>t4;cout<<tree.ask_last(n,t2,t3,t4)<<'\n';break;
			case 5:cin>>t3>>t4;cout<<tree.ask_next(n,t2,t3,t4)<<'\n';break;
		}
	}
}
2024/11/8 10:21
加载中...