人生第一道树套树的题,卡了3个小时。。。。。。。。
简直是人生耻辱啊。
目测从此患上了树套树恐惧症。
还有就是为毛我写的Treap这么慢(=。=)竟然跑了8秒多,感觉要跪啊。
还有这200多行的代码看得我好虚啊。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<ctime>
#include<queue>
#include<cctype>
using namespace std;
const int N=50000+5;
const int M=2000000+5;
int lc[M],rc[M],key[M],sz[M],fix[M],cnt;
queue<int>q;
int id(){
if(q.size()){
int t=q.front();q.pop();
return t;
}else return ++cnt;
}
void pushup(int x){
sz[x]=sz[lc[x]]+sz[rc[x]]+1;
}
void lturn(int &x){
int k=rc[x];rc[x]=lc[k];lc[k]=x;sz[k]=sz[x];pushup(x);x=k;
}
void rturn(int &x){
int k=lc[x];lc[x]=rc[k];rc[k]=x;sz[k]=sz[x];pushup(x);x=k;
}
struct treap{
int root;
treap(){
root=0;
}
void insert(int &x,int v){
if(!x){
key[x=id()]=v;sz[x]=1;lc[x]=rc[x]=0;fix[x]=rand();
}
else{
sz[x]++;
if(v<key[x]){
insert(lc[x],v);
if(fix[lc[x]]<fix[x])rturn(x);
}else{
insert(rc[x],v);
if(fix[rc[x]]<fix[x])lturn(x);
}
}
}
void insert(int x){
insert(root,x);
}
void del(int &x,int v){
if(!x)return;
if(key[x]==v){
if(!lc[x]||!rc[x])q.push(x),x=lc[x]+rc[x];
else if(fix[lc[x]]<fix[rc[x]])rturn(x),sz[x]--,del(rc[x],v);
else lturn(x),sz[x]--,del(lc[x],v);
}else{
sz[x]--;
if(v<key[x])del(lc[x],v);
else del(rc[x],v);
}
}
void modify(int x,int y){
del(root,x);
insert(root,y);
}
int rank(int x,int k){
if(!x)return 0;
if(k<=key[x])return rank(lc[x],k);
else return sz[lc[x]]+1+rank(rc[x],k);
}
int rank(int x){
return rank(root,x);
}
int suc(int x,int k){
if(!x)return k;
if(key[x]<=k)return suc(rc[x],k);
else{
int r=suc(lc[x],k);
if(r==k)return key[x];
else return r;
}
}
int suc(int k){
return suc(root,k);
}
int pre(int x,int k){
if(!x)return k;
if(key[x]>=k)return pre(lc[x],k);
else{
int r=pre(rc[x],k);
if(r==k)return key[x];
else return r;
}
}
int pre(int k){
return pre(root,k);
}
void travel(int x){
if(!x)return;
travel(lc[x]);
printf("%d ",key[x]);
travel(rc[x]);
}
void travel(){
travel(root);
}
};
struct Node{
int l,r,lc,rc;
treap t;
};
struct SegmentTree{
int cnt,root;
Node tr[N<<2];
SegmentTree(){
cnt=0;
root=0;
}
void build(int &o,int l,int r){
o=++cnt;
tr[o].l=l;tr[o].r=r;
if(l==r)return;
else{
int mid=l+r>>1;
build(tr[o].lc,l,mid);
build(tr[o].rc,mid+1,r);
}
}
void build(int n){
build(root,1,n);
}
void insert(int o,int p,int x){
tr[o].t.insert(x);
int l=tr[o].l,r=tr[o].r;
if(l==r)return;
else{
int mid=l+r>>1;
if(p<=mid)insert(tr[o].lc,p,x);
else insert(tr[o].rc,p,x);
}
}
void modify(int o,int p,int x,int y){
//printf("%d %d\n",x,y);
tr[o].t.modify(x,y);
int l=tr[o].l,r=tr[o].r;
if(l==r)return;
else{
int mid=l+r>>1;
if(p<=mid)modify(tr[o].lc,p,x,y);
else modify(tr[o].rc,p,x,y);
}
}
int rank(int o,int a,int b,int x){
int l=tr[o].l,r=tr[o].r;
if(l==a&&b==r)return tr[o].t.rank(x);
else{
int mid=l+r>>1;
if(b<=mid)return rank(tr[o].lc,a,b,x);
else if(mid<a)return rank(tr[o].rc,a,b,x);
else return rank(tr[o].lc,a,mid,x)+rank(tr[o].rc,mid+1,b,x);
}
}
int pre(int o,int a,int b,int x){
int l=tr[o].l,r=tr[o].r;
if(l==a&&b==r)return tr[o].t.pre(x);
else{
int mid=l+r>>1;
if(b<=mid)return pre(tr[o].lc,a,b,x);
else if(mid<a)return pre(tr[o].rc,a,b,x);
else{
int lans=pre(tr[o].lc,a,mid,x),rans=pre(tr[o].rc,mid+1,b,x);
if(lans==x)return rans;
if(rans==x)return lans;
return max(lans,rans);
}
}
}
int suc(int o,int a,int b,int x){
int l=tr[o].l,r=tr[o].r;
if(l==a&&b==r)return tr[o].t.suc(x);
else{
int mid=l+r>>1;
if(b<=mid)return suc(tr[o].lc,a,b,x);
else if(mid<a)return suc(tr[o].rc,a,b,x);
else{
int lans=suc(tr[o].lc,a,mid,x),rans=suc(tr[o].rc,mid+1,b,x);
if(lans==x)return rans;
if(rans==x)return lans;
return min(lans,rans);
}
}
}
void travel(int o){
if(!o)return;
printf("%d %d\n",tr[o].l,tr[o].r);
tr[o].t.travel();putchar('\n');
travel(tr[o].lc);travel(tr[o].rc);
}
void travel(){
travel(root);
}
}t;
int kth(int a,int b,int k){
int l=0,r=(1e8);
while(l<=r){
int mid=l+r>>1;
int rank=t.rank(1,a,b,mid);
if(rank>=k)r=mid-1;
else{
if(t.rank(1,a,b,mid+1)>=k)return mid;
else l=mid+1;
}
}
}
template<class T>void read(T &x){
static char c;
static bool f;
for(f=0;c=getchar(),!isdigit(c);)if(c=='-')f=1;
for(x=0;isdigit(c);c=getchar())x=x*10+c-'0';
if(f)x=-x;
}
int a[N];
int main(){
//freopen("a.in","r",stdin);
//freopen("a.out","w",stdout);
srand(34024902);
int n,m;read(n);read(m);
t.build(n);
int l,r,k,opt;
for(int i=1;i<=n;i++){
read(a[i]);
t.insert(1,i,a[i]);
}
//t.travel();
while(m--){
read(opt);
if(opt==1){
read(l);read(r);read(k);
printf("%d\n",t.rank(1,l,r,k)+1);
}else if(opt==2){
read(l);read(r);read(k);
printf("%d\n",kth(l,r,k));
}else if(opt==3){
read(l);read(k);
t.modify(1,l,a[l],k);
a[l]=k;
}else if(opt==4){
read(l);read(r);read(k);
printf("%d\n",t.pre(1,l,r,k));
}else if(opt==5){
read(l);read(r);read(k);
printf("%d\n",t.suc(1,l,r,k));
}
}
return 0;
}
为了洗刷这一耻辱,我决定……
用SBT重写一遍!
然后发现,还是跑了6秒多TAT。
好慢啊。。。。。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<cctype>
using namespace std;
const int N=50000+5;
const int M=2000000+5;
int lc[M],rc[M],key[M],sz[M],cnt;
queue<int>q;
int id(){
if(q.size()){
int t=q.front();q.pop();
return t;
}else return ++cnt;
}
void pushup(int x){
sz[x]=sz[lc[x]]+sz[rc[x]]+1;
}
void lturn(int &x){
int k=rc[x];rc[x]=lc[k];lc[k]=x;sz[k]=sz[x];pushup(x);x=k;
}
void rturn(int &x){
int k=lc[x];lc[x]=rc[k];rc[k]=x;sz[k]=sz[x];pushup(x);x=k;
}
void maintain(int &x,bool flag){
if(!flag){
if(sz[lc[lc[x]]]>sz[rc[x]])rturn(x);
else if(sz[rc[lc[x]]]>sz[rc[x]]){
lturn(lc[x]);
rturn(x);
}else return;
}else{
if(sz[rc[rc[x]]]>sz[lc[x]])lturn(x);
else if(sz[lc[rc[x]]]>sz[lc[x]]){
rturn(rc[x]);
lturn(x);
}else return;
}
maintain(lc[x],false);maintain(rc[x],true);
maintain(x,true);maintain(x,false);
}
struct SBT{
int root;
SBT(){
root=0;
}
void insert(int &x,int v){
if(!x){
key[x=id()]=v;sz[x]=1;lc[x]=rc[x]=0;
}
else{
sz[x]++;
if(v<key[x])insert(lc[x],v);
else insert(rc[x],v);
maintain(x,v>=key[x]);
}
}
void insert(int x){
insert(root,x);
}
int del(int &x,int v){
sz[x]--;
if(key[x]==v||(v<key[x]&&!lc[x])||(v>key[x]&&!rc[x])){
int r=key[x];
if(!lc[x]||!rc[x])x=lc[x]+rc[x];
else key[x]=del(lc[x],key[x]+1);
return r;
}else{
if(v<key[x])return del(lc[x],v);
else return del(rc[x],v);
}
}
void modify(int x,int y){
del(root,x);
insert(root,y);
}
int rank(int x,int k){
if(!x)return 0;
if(k<=key[x])return rank(lc[x],k);
else return sz[lc[x]]+1+rank(rc[x],k);
}
int rank(int x){
return rank(root,x);
}
int suc(int x,int k){
if(!x)return k;
if(key[x]<=k)return suc(rc[x],k);
else{
int r=suc(lc[x],k);
if(r==k)return key[x];
else return r;
}
}
int suc(int k){
return suc(root,k);
}
int pre(int x,int k){
if(!x)return k;
if(key[x]>=k)return pre(lc[x],k);
else{
int r=pre(rc[x],k);
if(r==k)return key[x];
else return r;
}
}
int pre(int k){
return pre(root,k);
}
void travel(int x){
if(!x)return;
travel(lc[x]);
printf("%d ",key[x]);
travel(rc[x]);
}
void travel(){
travel(root);
}
};
struct Node{
int l,r,lc,rc;
SBT t;
};
struct SegmentTree{
int cnt,root;
Node tr[N<<2];
SegmentTree(){
cnt=0;
root=0;
}
void build(int &o,int l,int r){
o=++cnt;
tr[o].l=l;tr[o].r=r;
if(l==r)return;
else{
int mid=l+r>>1;
build(tr[o].lc,l,mid);
build(tr[o].rc,mid+1,r);
}
}
void build(int n){
build(root,1,n);
}
void insert(int o,int p,int x){
tr[o].t.insert(x);
int l=tr[o].l,r=tr[o].r;
if(l==r)return;
else{
int mid=l+r>>1;
if(p<=mid)insert(tr[o].lc,p,x);
else insert(tr[o].rc,p,x);
}
}
void modify(int o,int p,int x,int y){
//printf("%d %d\n",x,y);
tr[o].t.modify(x,y);
int l=tr[o].l,r=tr[o].r;
if(l==r)return;
else{
int mid=l+r>>1;
if(p<=mid)modify(tr[o].lc,p,x,y);
else modify(tr[o].rc,p,x,y);
}
}
int rank(int o,int a,int b,int x){
int l=tr[o].l,r=tr[o].r;
if(l==a&&b==r)return tr[o].t.rank(x);
else{
int mid=l+r>>1;
if(b<=mid)return rank(tr[o].lc,a,b,x);
else if(mid<a)return rank(tr[o].rc,a,b,x);
else return rank(tr[o].lc,a,mid,x)+rank(tr[o].rc,mid+1,b,x);
}
}
int pre(int o,int a,int b,int x){
int l=tr[o].l,r=tr[o].r;
if(l==a&&b==r)return tr[o].t.pre(x);
else{
int mid=l+r>>1;
if(b<=mid)return pre(tr[o].lc,a,b,x);
else if(mid<a)return pre(tr[o].rc,a,b,x);
else{
int lans=pre(tr[o].lc,a,mid,x),rans=pre(tr[o].rc,mid+1,b,x);
if(lans==x)return rans;
if(rans==x)return lans;
return max(lans,rans);
}
}
}
int suc(int o,int a,int b,int x){
int l=tr[o].l,r=tr[o].r;
if(l==a&&b==r)return tr[o].t.suc(x);
else{
int mid=l+r>>1;
if(b<=mid)return suc(tr[o].lc,a,b,x);
else if(mid<a)return suc(tr[o].rc,a,b,x);
else{
int lans=suc(tr[o].lc,a,mid,x),rans=suc(tr[o].rc,mid+1,b,x);
if(lans==x)return rans;
if(rans==x)return lans;
return min(lans,rans);
}
}
}
void travel(int o){
if(!o)return;
printf("%d %d\n",tr[o].l,tr[o].r);
tr[o].t.travel();putchar('\n');
travel(tr[o].lc);travel(tr[o].rc);
}
void travel(){
travel(root);
}
}t;
int kth(int a,int b,int k){
int l=0,r=(1e8);
while(l<=r){
int mid=l+r>>1;
int rank=t.rank(1,a,b,mid);
if(rank>=k)r=mid-1;
else{
if(t.rank(1,a,b,mid+1)>=k)return mid;
else l=mid+1;
}
}
}
template<class T>void read(T &x){
static char c;
static bool f;
for(f=0;c=getchar(),!isdigit(c);)if(c=='-')f=1;
for(x=0;isdigit(c);c=getchar())x=x*10+c-'0';
if(f)x=-x;
}
int a[N];
int main(){
//freopen("a.in","r",stdin);
//freopen("a.out","w",stdout);
int n,m;read(n);read(m);
t.build(n);
int l,r,k,opt;
for(int i=1;i<=n;i++){
read(a[i]);
t.insert(1,i,a[i]);
}
//t.travel();
while(m--){
read(opt);
if(opt==1){
read(l);read(r);read(k);
printf("%d\n",t.rank(1,l,r,k)+1);
}else if(opt==2){
read(l);read(r);read(k);
printf("%d\n",kth(l,r,k));
}else if(opt==3){
read(l);read(k);
t.modify(1,l,a[l],k);
a[l]=k;
}else if(opt==4){
read(l);read(r);read(k);
printf("%d\n",t.pre(1,l,r,k));
}else if(opt==5){
read(l);read(r);read(k);
printf("%d\n",t.suc(1,l,r,k));
}
}
return 0;
}