您的位置:首页 > 其它

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

2016-03-10 19:02 381 查看
分块 就是分块嘛!
 

#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;
}


 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: