您的位置:首页 > 其它

【权值分块】bzoj3224 Tyvj 1728 普通平衡树

2014-11-14 16:07 411 查看
权值分块和权值线段树的思想一致,离散化之后可以代替平衡树的部分功能。

部分操作的时间复杂度:

插入删除全局排名全局K大前驱后继全局最值按值域删除元素
O(1)O(1)O(sqrt(n))O(sqrt(n))O(sqrt(n))O(sqrt(n))O(sqrt(n))O(sqrt(n))(懒标记)
当然,因为要离散化,所以只能离线。

代码很短,很快,比我的Splay短一倍,快一倍,现在在bzoj上rank6。

#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
#define N 100001
struct Point{int v,p;}t
;
bool operator < (const Point &a,const Point &b){return a.v<b.v;}
int n,op
,a
,ma
,en,l[800],r[800],sumv[800],sz,sum,num
,b
,Num,CH[12];
inline void R(int &x){
char c=0;int f=1;
for(;c<'0'||c>'9';c=getchar())if(c=='-')f=-1;
for(x=0;c>='0'&&c<='9';c=getchar())(x*=10)+=(c-'0');
x*=f;
}
inline void P(int x)
{
if(!x){putchar('0');puts("");return;}
if(x<0){putchar('-');x=-x;}Num=0;
while(x>0)CH[++Num]=x%10,x/=10;
while(Num)putchar(CH[Num--]+48);puts("");
}
void makeblock()
{
sz=sqrt(en); if(!sz) sz=1;
for(sum=1;sum*sz<n;sum++)
{
l[sum]=r[sum-1]+1;
r[sum]=sz*sum;
for(int i=l[sum];i<=r[sum];i++) num[i]=sum;
}
l[sum]=r[sum-1]+1;
r[sum]=n;
for(int i=l[sum];i<=r[sum];i++) num[i]=sum;
}
inline void Insert(const int &x){b[x]++; sumv[num[x]]++;}
inline void Delete(const int &x){b[x]--; sumv[num[x]]--;}
inline int Rank(const int &x)
{
int cnt=0;
for(int i=1;i<num[x];i++) cnt+=sumv[i];
for(int i=l[num[x]];i<x;i++) cnt+=b[i];
return cnt+1;
}
inline int Kth(const int &x)
{
int cnt=0;
for(int i=1;;i++)
{
cnt+=sumv[i];
if(cnt>=x)
{
cnt-=sumv[i];
for(int j=l[i];;j++)
{cnt+=b[j]; if(cnt>=x) return j;}
}
}
}
inline int Next(const int &x)
{
for(int i=x+1;i<=r[num[x]];i++) if(b[i]) return i;
for(int i=num[x]+1;;i++) if(sumv[i])
for(int j=l[i];;j++)
if(b[j]) return j;
}
inline int Pre(const int &x)
{
for(int i=x-1;i>=l[num[x]];i--) if(b[i]) return i;
for(int i=num[x]-1;;i--) if(sumv[i])
for(int j=r[i];;j--)
if(b[j]) return j;
}
int main()
{
R(n); for(int i=1;i<=n;i++)
{
R(op[i]); R(t[i].v);
t[i].p=i;
}
sort(t+1,t+n+1);
ma[a[t[1].p]=++en]=t[1].v;
for(int i=2;i<=n;i++)
{
if(t[i].v!=t[i-1].v) en++;
ma[a[t[i].p]=en]=t[i].v;
}
makeblock();
for(int i=1;i<=n;i++)
{
if(op[i]==1) Insert(a[i]);
else if(op[i]==2) Delete(a[i]);
else if(op[i]==3) P(Rank(a[i]));
else if(op[i]==4) P(ma[Kth(ma[a[i]])]);
else if(op[i]==5) P(ma[Pre(a[i])]);
else P(ma[Next(a[i])]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: