#include<cstdio> #include<cstring> #include<cstdlib> using namespace std; inline int min(int a,int b) {return (a<b?a:b);} inline int max(int a,int b) {return (a>b?a:b);} inline int abs(int a) {return (a<0?-a:a);} char c; bool flag; inline void read(int &a) { a=0;flag=false; do c=getchar();while(c!='-'&&(c<'0'||c>'9')); if(c=='-')c=getchar(),flag=true; while(c<='9'&&c>='0')a=(a<<3)+(a<<1)+c-'0',c=getchar(); if(flag)a=-a; } inline void print(int a) { if(a<0)putchar('-'),a=-a; if(a<10){putchar('0'+a),putchar('\n');return;} long long base=1; while(base<=a) base=(base<<3)+(base<<1); base/=10; while(base)putchar('0'+a/base),a%=base,base/=10; putchar('\n'); } struct Node { Node *f,*lc,*rc; int data,rank,size; inline bool l(){return this->f->lc==this;} }; Node *sta=new Node[1000001]; int cc; int max_Con=1000000; Node *stack[1000001]; inline Node* Node_Stackpop() { return stack[cc--]; } inline void Node_Stackpush(Node *a) {stack[++cc]=a;} Node *empty; inline void begin(){empty=new Node;empty->f=empty;empty->lc=empty->rc=empty;empty->data=empty->size=empty->rank=0;cc=max_Con;for(int i=0;i<=max_Con;i++)stack[i]=sta+i;} inline Node *New_Node(){Node *tp=Node_Stackpop();tp->lc=tp->rc=empty;tp->size=1;tp->rank=1;return tp;} inline void up_data(Node *a) {a->rank=a->lc->size+1;a->size=a->lc->size+a->rc->size+1;} inline void lc_change(Node *a) { if(a->f==a) return ; Node *newf; if(a->f->f==a->f) newf=a; else if(a->f->l()) a->f->f->lc=a,newf=a->f->f; else a->f->f->rc=a,newf=a->f->f; a->rc->f=a->f; a->f->lc=a->rc; a->rc=a->f; a->f->f=a; a->f=newf; up_data(a->rc); up_data(a); } inline void rc_change(Node *a) { if(a->f==a) return ; Node *newf; if(a->f->f==a->f) newf=a; else if(a->f->l()) a->f->f->lc=a,newf=a->f->f; else a->f->f->rc=a,newf=a->f->f; a->lc->f=a->f; a->f->rc=a->lc; a->lc=a->f; a->f->f=a; a->f=newf; up_data(a->lc); up_data(a); } inline void Change(Node *a) {a->l()?lc_change(a):rc_change(a);} inline void Twice_Change(Node *a) {if(a->l()==a->f->l())Change(a->f);else Change(a);Change(a);} inline void Spaly(Node *a) {while(a->f->f!=a->f)Twice_Change(a);while(a->f!=a)Change(a);} inline void insert(Node *a,Node *data) { if(a->data>=data->data) if(a->lc==empty) a->lc=data,data->f=a,Spaly(data); else insert(a->lc,data); else if(a->rc==empty) a->rc=data,data->f=a,Spaly(data); else insert(a->rc,data); } const int INF=100000000; int Find_Rank(Node *a,int data) { if(a->data>data) if(a->lc==empty) return 1; else return Find_Rank(a->lc,data); else if(a->data==data) if(a->lc!=empty) return min(a->rank,Find_Rank(a->lc,data)); else return a->rank; else if(a->rc==empty) return a->rank+1; else return Find_Rank(a->rc,data)+a->rank; } int Pre(Node *a,int data) { if(a->data>=data) if(a->lc==empty) return -INF; else return Pre(a->lc,data); else if(a->rc==empty) return a->data; else return max(a->data,Pre(a->rc,data)); } bool Has(Node *a,int data) { if(a->data==data)return true; if(a->data>data) if(a->lc==empty) return false; else return Has(a->lc,data); else if(a->rc==empty) return false; else return Has(a->rc,data); } int Aft(Node *a,int data) { if(a->data>data) if(a->lc==empty) return a->data; else return min(a->data,Aft(a->lc,data)); else if(a->rc==empty) return INF; else return Aft(a->rc,data); } int Find_Data(Node *a,int rank) { if(a->rank==rank) return a->data; else if(a->rank>rank) return Find_Data(a->lc,rank); return Find_Data(a->rc,rank-a->rank); } struct Segement_Node { Node *root; int l,r; }Segement_Tree[1000001]; int data[1000001]; inline void Delete(Node *a,int Sege_place) { Node *first; if(a==Segement_Tree[Sege_place].root) if(a->lc!=empty) Segement_Tree[Sege_place].root=a->lc; else Segement_Tree[Sege_place].root=a->rc; else; while(a->lc!=empty||a->rc!=empty) if(a->lc!=empty) Change(a->lc); else Change(a->rc); (a->l()?a->f->lc:a->f->rc)=empty; up_data(a->f); Spaly(a->f); Segement_Tree[Sege_place].root=a->f; Node_Stackpush(a); } void era(Node *a,int data,int Sege_place) { if(a->data==data) Delete(a,Sege_place); else if(a->data<data) era(a->rc,data,Sege_place),up_data(a); else if(a->data>data) era(a->lc,data,Sege_place),up_data(a); } void Build_Segement_Tree(int place,int l,int r) { Segement_Tree[place].l=l; Segement_Tree[place].r=r; Segement_Tree[place].root=New_Node(); Segement_Tree[place].root->f=Segement_Tree[place].root; Segement_Tree[place].root->data=data[l]; int i; Node *tp=Segement_Tree[place].root; for(i=l+1;i<=r;i++) tp=New_Node(),tp->data=data[i],insert(Segement_Tree[place].root,tp), Segement_Tree[place].root=tp; if(l^r) Build_Segement_Tree(place<<1,l,(l+r)>>1),Build_Segement_Tree(place<<1|1,1+((l+r)>>1),r); } int Change_Segement_Tree(int place,int l,int data) { int del_data; if(Segement_Tree[place].l^Segement_Tree[place].r) { if(Segement_Tree[place<<1].r>=l) del_data=Change_Segement_Tree(place<<1,l,data); else del_data=Change_Segement_Tree(place<<1|1,l,data); era(Segement_Tree[place].root,del_data,place); Node *tp=New_Node(); tp->data=data; insert(Segement_Tree[place].root,tp), Segement_Tree[place].root=tp; return del_data; } else { del_data=Segement_Tree[place].root->data; Segement_Tree[place].root->data=data; return del_data; } } bool Segement_Has(int place,int l,int r,int data) { if(l<=Segement_Tree[place].l&&Segement_Tree[place].r<=r) return Has(Segement_Tree[place].root,data); int re=0; if(Segement_Tree[place<<1].r>=l) re=Segement_Has(place<<1,l,r,data); if(re)return true; if(Segement_Tree[place<<1|1].l<=r) re=Segement_Has(place<<1|1,l,r,data); return re; } int Segement_Rank(int place,int l,int r,int data) { if(l<=Segement_Tree[place].l&&Segement_Tree[place].r<=r) return Find_Rank(Segement_Tree[place].root,data); int re=0; if(Segement_Tree[place<<1].r>=l) re+=Segement_Rank(place<<1,l,r,data)-1; if(Segement_Tree[place<<1|1].l<=r) re+=Segement_Rank(place<<1|1,l,r,data)-1; return re+1; } int Segement_Rank2(int place,int l,int r,int data) { if(l<=Segement_Tree[place].l&&Segement_Tree[place].r<=r) return Find_Rank(Segement_Tree[place].root,data); int re=0; if(Segement_Tree[place<<1].r>=l) re+=Segement_Rank2(place<<1,l,r,data)-1; if(Segement_Tree[place<<1|1].l<=r) re+=Segement_Rank2(place<<1|1,l,r,data)-1; return re+1; } int Segement_Pre(int place,int l,int r,int data) { if(l<=Segement_Tree[place].l&&Segement_Tree[place].r<=r) return Pre(Segement_Tree[place].root,data); int re=-INF; if(Segement_Tree[place<<1].r>=l) re=Segement_Pre(place<<1,l,r,data); if(Segement_Tree[place<<1|1].l<=r) re=max(re,Segement_Pre(place<<1|1,l,r,data)); return re; } int Segement_Aft(int place,int l,int r,int data) { if(l<=Segement_Tree[place].l&&Segement_Tree[place].r<=r) return Aft(Segement_Tree[place].root,data); int re=INF; if(Segement_Tree[place<<1].r>=l) re=Segement_Aft(place<<1,l,r,data); if(Segement_Tree[place<<1|1].l<=r) re=min(re,Segement_Aft(place<<1|1,l,r,data)); return re; } inline int Divid(int k,int l,int r) { int data,li=k,ri=Segement_Tree[1].root->size; int mid,cp; while(li<(ri-1)) { mid=(li+ri)>>1; data=Find_Data(Segement_Tree[1].root,mid); if(Segement_Rank2(1,l,r,data)<=k) li=mid; else ri=mid-1; } data=Find_Data(Segement_Tree[1].root,li); if(Segement_Has(1,l,r,data)&&Segement_Rank2(1,l,r,Find_Data(Segement_Tree[1].root,ri))!=k) return data; else return Find_Data(Segement_Tree[1].root,ri); } int main() { int i,n,m,j,k,l; read(n),read(m); for(i=1;i<=n;i++) read(data[i]); begin(); int data; Build_Segement_Tree(1,1,n); for(i=1;i<=m;i++) { read(j); if(j==1) { read(k),read(l),read(data); print(Segement_Rank(1,k,l,data)); } else if(j==2) { read(j),read(k),read(l); print(Divid(l,j,k)); } else if(j==3) { read(j),read(k); Change_Segement_Tree(1,j,k); } else if(j==4) { read(j),read(k),read(l); print(Segement_Pre(1,j,k,l)); } else if(j==5) { read(j),read(k),read(l); print(Segement_Aft(1,j,k,l)); } } return 0; }
反正就是线段树套平衡树。。。不过听Claris说把外层换成权值线段树然后用内部平衡树维护区间可以少一个log。。。Orz反正我是不会
一开始一直RE然后才发现是自己脑残New Node的时候没有返回tp的地址 windows上居然可以过去 误
不管怎么说 还是自己太弱了QAQ