您的位置:首页 > 其它

bzoj3196: Tyvj 1730 二逼平衡树

2016-05-29 20:33 267 查看
传送们:http://www.lydsy.com/JudgeOnline/problem.php?id=3196

题解:线段树+treap

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cmath>
#include<cstdio>
#define inf 100000000
#define N 200001
#define M 3000001
using namespace std;
int n,m,sz,ans,a
;
int ls[M],rs[M],rnd[M],v[M],s[M],w[M];
int root
;
int read()
{
int x=0; char ch; bool bo=0;
while (ch=getchar(),ch<'0'||ch>'9') if (ch=='-') bo=1;
while (x=x*10+ch-'0',ch=getchar(),ch>='0'&&ch<='9');
if (bo) return -x; return x;
}
void updata(int k){s[k]=s[ls[k]]+s[rs[k]]+w[k];}
void rturn(int &k){int t=ls[k]; ls[k]=rs[t]; rs[t]=k; s[t]=s[k]; updata(k);    k=t;}
void lturn(int &k){int t=rs[k]; rs[k]=ls[t]; ls[t]=k; s[t]=s[k]; updata(k);    k=t;}
void insert(int &k,int val)
{
if(!k){k=++sz; s[k]=w[k]=1; v[k]=val; rnd[k]=rand();return;}
s[k]++;
if (v[k]==val)    w[k]++;
else if (val<v[k])     {insert(ls[k],val); if (rnd[ls[k]]<rnd[k]) rturn(k);}
else if (val>v[k])    {insert(rs[k],val); if (rnd[rs[k]]<rnd[k]) lturn(k);}
}

void build(int k,int l,int r,int pos,int val)
{
insert(root[k],val);
if (l==r) return ;
int mid=(l+r)>>1;
if (pos<=mid) build(k*2,l,mid,pos,val);
else build(k*2+1,mid+1,r,pos,val);
}
void del(int &k,int num)
{
if (v[k]==num)
{
if (w[k]>1){w[k]--; s[k]--; return;}
if (ls[k]*rs[k]==0) k=ls[k]+rs[k];
else if (rnd[ls[k]]<rnd[rs[k]]){rturn(k); del(k,num);}
else {lturn(k); del(k,num);}
}
else
if (v[k]>num) {del(ls[k],num); s[k]--;}
else{del(rs[k],num); s[k]--;}
}
void ask_rank(int k,int num)
{
if (!k) return;
if (v[k]==num){ans+=s[ls[k]]; return;}
else if (v[k]>num) ask_rank(ls[k],num);
else if (v[k]<num) {ans+=s[ls[k]]+w[k]; ask_rank(rs[k],num);}
}
void query_rank(int k,int l,int r,int x,int y,int num)
{
if (l==x && y==r){ask_rank(root[k],num); return;}
int mid=(l+r)>>1;
if (y<=mid)    query_rank(k*2,l,mid,x,y,num);
else if (mid<x)    query_rank(k*2+1,mid+1,r,x,y,num);
else
{
query_rank(k*2,l,mid,x,mid,num);
query_rank(k*2+1,mid+1,r,mid+1,y,num);
}
}
void query_k(int x,int y,int num)
{
int l=0,r=inf,tmp;
while (l<r)
{
//cout<<l<<" "<<r<<endl;
int mid=(l+r)>>1; ans=1;
query_rank(1,1,n,x,y,mid);
//cout<<"      ans     "<<ans<<endl;
if (ans>num)    r=mid;
else {l=mid+1; tmp=mid;}
}
printf("%d\n",tmp);
}
void pre(int k,int pos)
{
if (!k) return;
if (v[k]<pos) {ans=max(ans,v[k]); pre(rs[k],pos);}
else pre(ls[k],pos);
}
void next(int k,int pos)
{
if (!k) return;
if (v[k]>pos) {ans=min(ans,v[k]); next(ls[k],pos);}
else next(rs[k],pos);
}
void query_pre(int k,int l,int r,int x,int y,int pos)
{
if (l==x && r==y){ pre(root[k],pos); return;
}
int mid=(l+r)>>1;
if (y<=mid)    query_pre(k*2,l,mid,x,y,pos);
else if (mid<x) query_pre(k*2+1,mid+1,r,x,y,pos);
else
{
query_pre(k*2,l,mid,x,mid,pos);
query_pre(k*2+1,mid+1,r,mid+1,y,pos);
}
}
void query_next(int k,int l,int r,int x,int y,int pos)
{    if (k!=0)
//cout<<" "<<k<<" "<<l<<" "<<r<<" "<<x<<" "<<y<<" "<<pos<<endl;
if (l==x && r==y){ next(root[k],pos); return;
}
int mid=(l+r)>>1;
if (y<=mid)    query_next(k*2,l,mid,x,y,pos);
else if (mid<x) query_next(k*2+1,mid+1,r,x,y,pos);
else
{
query_next(k*2,l,mid,x,mid,pos);
query_next(k*2+1,mid+1,r,mid+1,y,pos);
}
}
void change(int k,int l,int r,int pos,int now,int pre)
{
del(root[k],pre);
insert(root[k],now);
if (l==r) return;
int mid=(l+r)>>1;
if (pos<=mid) change(k*2,l,mid,pos,now,pre);
else change(k*2+1,mid+1,r,pos,now,pre);
}
int main()
{
n=read(),m=read();
for (int i=1; i<=n; i++) a[i]=read();
for (int i=1; i<=n; i++) build(1,1,n,i,a[i]);
int opt,l,r,k,pos;
for (int i=1; i<=m; i++)
{
opt=read();
if (opt==1){l=read(),r=read(),k=read();ans=1; query_rank(1,1,n,l,r,k);}
if (opt==2){l=read(),r=read(),k=read();    query_k(l,r,k);}
if (opt==3){pos=read(),k=read();change(1,1,n,pos,k,a[pos]);a[pos]=k;}
if (opt==4){l=read(),r=read(),k=read();ans=0; query_pre(1,1,n,l,r,k);}
if (opt==5){l=read(),r=read(),k=read();ans=inf; query_next(1,1,n,l,r,k);}
if (opt!=3 && opt!=2) printf("%d\n",ans);
}
}


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