RT. 快优化到头了,不知道是不是假了,按第二篇题解的写法写的,就是外层权值,内层位置。
求大佬调,谢谢
#include<bits/stdc++.h>
using namespace std;
const int N=5e4+5;
const int LOG2N=log2(N)+2;
int n,m;
const int INF=2147483647;
//Unit FHQTreap
struct interval{
int l,r;
interval(){l=r=0;}
interval(int ll,int rr){l=ll,r=rr;}
inline int mid(){return (l+r)/2;}
inline interval ls(){
return interval(l,mid());
}
inline interval rs(){
return interval(mid()+1,r);
}
inline bool isleaf(){
return l==r;
}
inline bool contains(interval &o){
return l<=o.l&&o.r<=r;
}
};
inline interval global(){
return interval(0,1e8);
}
namespace FHQ{
mt19937 _rng(time(0));
struct _{
int ls,rs;
int siz,val,rnd;
_(){}
_(int v){siz=1,val=v,rnd=(_rng)(),ls=rs=0;}
}s[N*LOG2N*4];
void Update(int p){
s[p].siz=s[s[p].ls].siz+s[s[p].rs].siz+1;
}
int tot;
int Alloc(int val){
int id=++tot;
s[id]=_(val);
return id;
}
void SplitByVal(int p,int &x,int &y,int val){
if(!p){
x=y=0;
return;
}
if(s[p].val<=val){
x=p,SplitByVal(s[p].rs,s[p].rs,y,val);
}else{
y=p,SplitByVal(s[p].ls,x,s[p].ls,val);
}
Update(p);
}
int Merge(int x,int y){
if(!x||!y) return x+y;
if(s[x].rnd>s[y].rnd){
s[x].rs=Merge(s[x].rs,y);
Update(x);
return x;
}else{
s[y].ls=Merge(x,s[y].ls);
Update(y);
return y;
}
}
class FHQTreap{
public:
int root;
FHQTreap(){
root=0;
}
void Insert(int v){
int t1,t2;//all is well
SplitByVal(root,t1,t2,v);
root=Merge(Merge(t1,Alloc(v)),t2);
}
void Delete(int v){
int t1,t2,t3;
SplitByVal(root,t1,t3,v);
SplitByVal(t1,t1,t2,v-1);
root=Merge(t1,t3);
}
void P(int p,int &ans,int v){
if(!p) return;
if(s[p].val<=v){
ans+=s[s[p].ls].siz+1;
P(s[p].rs,ans,v);
}else{
P(s[p].ls,ans,v);
}
}
int Query(interval &q){
int l=q.l,r=q.r;
int ans1=0,ans2=0;
P(root,ans1,r),P(root,ans2,l-1);
return ans1-ans2;
}
};
}
namespace SEG{
//Unit SegmentTree
struct _{
int ls,rs;
FHQ::FHQTreap fhq;
_(){
ls=rs=0;
}
}s[N*LOG2N];
int tot;
int Alloc(){
int id=++tot;
s[id]=_();
return id;
}
class SegmentTree{
public:
int root;
SegmentTree(){
root=0;
}
void Insert(int &p,interval t,int val,int x){//Actually insert x...
if(!p) p=Alloc();
s[p].fhq.Insert(x);
if(t.isleaf()) return;
int mid=t.mid();
if(val<=mid) Insert(s[p].ls,t.ls(),val,x);
else Insert(s[p].rs,t.rs(),val,x);
}
void Remove(int &p,interval t,int val,int x){//Actually remove x...
if(!p) return;
s[p].fhq.Delete(x);
if(t.isleaf()){
return;
}
int mid=t.mid();
if(val<=mid) Remove(s[p].ls,t.ls(),val,x);
else Remove(s[p].rs,t.rs(),val,x);
}
interval q,r;
int Rank(int p,interval t){
if(!p) return 0;
if(q.contains(t)) return s[p].fhq.Query(r);
int mid=t.mid(),res=0;
if(q.l<=mid) res+=Rank(s[p].ls,t.ls());
if(q.r>mid) res+=Rank(s[p].rs,t.rs());
return res;
}
int Value(int p,interval t,int k){
if(!p) return -INF;
if(t.isleaf()) return t.l;
int res=s[s[p].ls].fhq.Query(r);
if(k>res) return Value(s[p].rs,t.rs(),k-res);
else return Value(s[p].ls,t.ls(),k);
}
int Prev(int p,interval t){
if(!p) return -INF;
if(s[p].fhq.Query(r)==0) return -INF;
if(t.isleaf()) return t.l;
int mid=t.mid(),res=-INF;
if(q.l<=mid) res=max(res,Prev(s[p].ls,t.ls()));
if(q.r>mid) res=max(res,Prev(s[p].rs,t.rs()));
return res;
}
int Next(int p,interval t){
if(!p) return INF;
if(s[p].fhq.Query(r)==0) return INF;
if(t.isleaf()) return t.l;
int mid=t.mid(),res=INF;
if(q.l<=mid) res=min(res,Next(s[p].ls,t.ls()));
if(q.r>mid) res=min(res,Next(s[p].rs,t.rs()));
return res;
}
void Modify(int x,int k,int ori){
Remove(root,global(),ori,x);
Insert(root,global(),k,x);
}
};
}
inline int read(){
register int w=0,x=0;char ch;
while(ch<'0'||ch>'9'){w|=ch=='-';ch=getchar();}
while('0'<=ch&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return w?-x:x;
}
SEG::SegmentTree seg;
int a[N];
int main(){
n=read(),m=read();
for(int i=1;i<=n;i++){
a[i]=read();
seg.Insert(seg.root,global(),a[i],i);
}
while(m--){
int op,l,r,k;
op=read(),l=read(),r=read();
if(op!=3) k=read();
switch(op){
case 1:{
seg.q=interval(0,k-1),seg.r=interval(l,r);
printf("%d\n",seg.Rank(seg.root,global())+1);
break;
}
case 2:{
seg.r=interval(l,r);
printf("%d\n",seg.Value(seg.root,global(),k));
break;
}
case 3:{
seg.Modify(l,r,a[l]);
a[l]=r;
break;
}
case 4:{
seg.q=interval(0,k-1),seg.r=interval(l,r);
printf("%d\n",seg.Prev(seg.root,global()));
break;
}
case 5:{
seg.q=interval(k+1,1e8),seg.r=interval(l,r);
printf("%d\n",seg.Next(seg.root,global()));
break;
}
}
}
}