【BZOJ 3196】 Tyvj 1730 二逼平衡树 分块

分块 就是分块嘛!

 

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <cmath>
#define MAXN 1000000
#define INF 1000000000
#define MO 233333333
#define LL long long
using namespace std;
int num[300][300];
int init[50000+1];
int n,m;
int cnt,lenth;
int Find(int tmp[300],int k)
{
	int L=1,R=tmp[0];
	while(L<R)
	{
		int mid=(L+R)/2;
		if(tmp[mid]>=k) R=mid;
		else L=mid+1;
	}
	if(tmp[L]>=k)return L-1;
	return L;
}
int Rank(int L,int R,int k)
{
	int ans=0;
	int s=(L+lenth-1)/lenth,t=(R+lenth-1)/lenth;// cout<<lenth<<endl;
	if(s!=t)
	{
		for(int i=L;i<=lenth*s;i++)
			if(init[i]<k)
				ans++;
		s++;
		for(int i=R;i>=lenth*(t-1)+1;i--)
			if(init[i]<k)
				ans++;
		for(int i=s;i<t;i++)
			ans+=Find(num[i],k);
	}
	else
	{
		for(int i=L;i<=R;i++)
			if(init[i]<k) 
				ans++;
	}
	return ans+1;
}
int Kth(int L,int R,int k)
{
	int s=0,t=100000000;
	int ans=0;
	while(s<t)
	{
		int mid=(s+t)/2;
		if(Rank(L,R,mid)>k) t=mid;
		else s=mid+1,ans=mid;
	}
	return ans;
}
void Change(int loc,int k)
{
	init[loc]=k;
	int tmp=(loc+lenth-1)/lenth;
	for(int i=1;i<=num[tmp][0];i++)
		num[tmp][i]=init[(tmp-1)*lenth+i];
	sort(num[tmp]+1,num[tmp]+num[tmp][0]+1);
}
int Before(int L,int R,int k)
{
	int s=(L+lenth-1)/lenth,t=(R+lenth-1)/lenth;
	int mmax=-1;//cout<<s<<' '<<t<<endl;
	if(s!=t)
	{
		for(int i=L;i<=s*lenth;i++)
			if(init[i]<k)
				mmax=max(mmax,init[i]);
		s++;
		for(int i=R;i>=(s-1)*lenth;i--)
			if(init[i]<k)
				mmax=max(mmax,init[i]);
		for(int i=s;i<t;i++)
		{
			int x=Find(num[i],k);
			if(x!=0)
				mmax=max(num[i][x],mmax);
		}
	}
	else
	{
		for(int i=L;i<=R;i++)
			if(init[i]<k)
				mmax=max(mmax,init[i]);
	}
	return mmax;
}
int Find_After(int tmp[300],int k)
{
	int L=1,R=tmp[0];
	while(L<R)
	{
		int mid=(L+R)/2;
		if(tmp[mid+1]<=k) L=mid+1;
		else R=mid;
	}
	if(tmp[L]<=k) return L+1;
	return L;
}
int After(int L,int R,int k)
{
	int s=(L+lenth-1)/lenth,t=(R+lenth-1)/lenth;
	int mmin=100000000+1;
	if(s!=t)
	{
		for(int i=L;i<=s*lenth;i++)
			if(init[i]>k)
				mmin=min(mmin,init[i]);
		s++;
		for(int i=R;i>=(s-1)*lenth;i--)
			if(init[i]>k)
				mmin=min(mmin,init[i]);
		for(int i=s;i<t;i++)
		{
			int x=Find_After(num[i],k);
			if(x!=num[i][0]+1)
				mmin=min(num[i][x],mmin);
		}
	}
	else
	{
		for(int i=L;i<=R;i++)
			if(init[i]>k)
				mmin=min(mmin,init[i]);
	}
	return mmin;
}
int main()
{
//	freopen("a.in","r",stdin);
	cin>>n>>m; //cout<<n<<endl;
	for(int i=1;i<=n;i++) scanf("%d",&init[i]);
	lenth=sqrt(n)+2;
	cnt=lenth;
	for(int i=1;i<=cnt;i++)
	{
		for(int j=1;j<=lenth;j++)
			num[i][j]=init[(i-1)*lenth+j];
		sort(num[i]+1,num[i]+lenth+1);
		num[i][0]=lenth;
	}
	if(n%lenth!=0)
	{
		cnt++;
		num[cnt][0]=n%lenth;
		for(int i=1;i<=num[cnt][0];i++)
			num[cnt][i]=init[(cnt-1)*lenth+i];
		sort(num[cnt]+1,num[cnt]+1+num[cnt][0]);
	}
	int L,R,pos,opt,k;
	for(int i=1;i<=m;i++)
	{
		scanf("%d",&opt);
		switch (opt)
		{
			case 1:
				{
					scanf("%d %d %d",&L,&R,&k); 
					printf("%d\n",Rank(L,R,k));
					break;
				}
			case 2:
				{
					scanf("%d %d %d",&L,&R,&k);
					printf("%d\n",Kth(L,R,k));
					break;
				}
			case 3:
				{
					scanf("%d %d",&pos,&k);
					Change(pos,k);
					break; 
				}
			case 4:
				{
					scanf("%d %d %d",&L,&R,&k);
					printf("%d\n",Before(L,R,k));
					break;
				}
			case 5:
				{
					scanf("%d %d %d",&L,&R,&k);
					printf("%d\n",After(L,R,k)); 
					break;
				}
		}


	}


	return 0;
}

 

posted @ 2016-01-15 14:00  sxb_201  阅读(230)  评论(2编辑  收藏  举报