题意:太难说了。。手动去看吧反正不是权限题。

膜拜VFK大爷的神题!

其实一开始思路挺清楚的,如果我们能做到用一个实数去代表“数”,这就是裸的动态区间最值查询。

关键是怎么用实数去表示。如果我们单纯的把两个数进行O(1)运算去得到一个实数,这样很轻松就会被卡掉,因为无论是longlong还是double都是有限度的。怎么做呢?

这里有一个技巧:我们维护一个重量平衡树,每个节点管辖一个区间,这个区间的中位数为这个点的权值,而它的左儿子管辖左半边,右儿子管辖右半边。

问题来了,这不是差不多吗?并不是这样。因为我们会重构,树高有保证,所以我们肯定能表示出每一个数,而且还是绰绰有余。

重量平衡树可以用不旋转的treap或替罪羊树。

(吐槽一句,第一次写替罪羊树,真的好TM难写啊还套了个线段树而且我常数大的飞起,写了一整天)

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define N 500005
  4 #define LL long long
  5 inline LL read(){
  6     LL x=0,f=1; char a=getchar();
  7     while(a<'0' || a>'9') {if(a=='-') f=-1; a=getchar();}
  8     while(a>='0' && a<='9') x=x*10+a-'0',a=getchar();
  9     return x*f;
 10 }
 11 int n,m; char st[5];
 12 LL MX;
 13 #define SGT Scapegoat_Tree
 14 #define ST Segment_Tree
 15 
 16 namespace Scapegoat_Tree{
 17     #define eps 1e-12
 18     const double alpha=0.75;
 19     int ltst,wh,size=1,tmp[N],root=1,anew;
 20     struct sgt{
 21         LL l,r,mid; int fir,sec;
 22         int son[2],sz;
 23     }tr[N];
 24     inline int dcmp(int x,int y){
 25         if(fabs((double)tr[x].sz*alpha-(double)tr[y].sz)<eps) return 0;
 26         else return (double)tr[x].sz*alpha>(double)tr[y].sz?1:-1;
 27     }
 28     inline void update(int x){
 29         tr[x].sz=tr[tr[x].son[0]].sz+tr[tr[x].son[1]].sz+1;
 30     }
 31     inline bool balance(int x){
 32         return dcmp(x,tr[x].son[0])>=0 && dcmp(x,tr[x].son[1])>=0;
 33     }
 34     void travel(int x){
 35         if(!x) return;
 36         travel(tr[x].son[0]);
 37         tmp[++tmp[0]]=x;
 38         travel(tr[x].son[1]);
 39     }
 40     void rebuild(int &x,int l,int r,LL L,LL R){
 41         if(l>r) {x=0; return;}
 42         int mid=(l+r)>>1;
 43         LL M=(L+R)/2;
 44         x=tmp[mid]; tr[x].l=L; tr[x].r=R; tr[x].mid=M;
 45         if(l==r) {tr[x].sz=1; tr[x].son[0]=0; tr[x].son[1]=0; return;}
 46         rebuild(tr[x].son[0],l,mid-1,L,M); rebuild(tr[x].son[1],mid+1,r,M,R);
 47         update(x);
 48     }
 49     void insert(int& x,LL L,LL R,int fir,int sec){
 50         if(!x) {x=++size; anew=x;tr[x]=(sgt){L,R,(L+R)/2,fir,sec,0,0,1}; return;}
 51         if(tr[tr[x].fir].mid==tr[fir].mid && tr[tr[x].sec].mid==tr[sec].mid) {anew=x; return;}
 52         else if(tr[tr[x].fir].mid==tr[fir].mid){
 53             if(tr[tr[x].sec].mid>tr[sec].mid) insert(tr[x].son[0],tr[x].l,tr[x].mid,fir,sec);
 54             else insert(tr[x].son[1],tr[x].mid,tr[x].r,fir,sec);
 55         }
 56         else{
 57             if(tr[tr[x].fir].mid>tr[fir].mid) insert(tr[x].son[0],tr[x].l,tr[x].mid,fir,sec);
 58             else insert(tr[x].son[1],tr[x].mid,tr[x].r,fir,sec);
 59         }
 60         update(x);
 61         if(tr[x].son[0] && !balance(tr[x].son[0])) ltst=x,wh=0;
 62         else if(tr[x].son[1] && !balance(tr[x].son[1])) ltst=x,wh=1;
 63         if(x==root && !balance(x)) tmp[0]=0,travel(root),rebuild(root,1,tmp[0],1,MX);
 64     }
 65 }
 66 namespace Segment_Tree{
 67     int a[N];
 68     struct seg{
 69         int l,r,son[2],mx_pos,num;         
 70     }tr[N];
 71     inline void update(int x){
 72         if(SGT::tr[tr[tr[tr[x].son[0]].mx_pos].num].mid==SGT::tr[tr[tr[tr[x].son[1]].mx_pos].num].mid){
 73             int le=tr[tr[x].son[0]].mx_pos,ri=tr[tr[x].son[1]].mx_pos;
 74             tr[x].mx_pos=tr[le].l<tr[ri].l?le:ri;
 75         }
 76         else if(SGT::tr[tr[tr[tr[x].son[0]].mx_pos].num].mid>SGT::tr[tr[tr[tr[x].son[1]].mx_pos].num].mid) 
 77         tr[x].mx_pos=tr[tr[x].son[0]].mx_pos;
 78         else tr[x].mx_pos=tr[tr[x].son[1]].mx_pos;
 79     }
 80     void build(int x,int l,int r){
 81         if(l==r) {tr[x]=(seg){l,r,0,0,x,1};return;}
 82         int mid=(l+r)>>1; tr[x].l=l; tr[x].r=r;
 83         tr[x].son[0]=x<<1; build(tr[x].son[0],l,mid);
 84         tr[x].son[1]=x<<1|1; build(tr[x].son[1],mid+1,r);
 85         update(x);
 86     }
 87     void modify(int x,int ai,int v){
 88         int l=tr[x].l,r=tr[x].r;
 89         if(l==r) {tr[x].num=v; return;}
 90         int mid=(l+r)>>1;
 91         if(ai<=mid) modify(tr[x].son[0],ai,v);
 92         else modify(tr[x].son[1],ai,v);
 93         update(x);
 94     }
 95     int query(int x,int L,int R){
 96         int l=tr[x].l,r=tr[x].r;
 97         if(l==L && r==R) return tr[x].mx_pos;
 98         int mid=(l+r)>>1;
 99         if(R<=mid) return query(tr[x].son[0],L,R);
100         else if(mid<L) return query(tr[x].son[1],L,R);
101         else{
102             int le=query(tr[x].son[0],L,mid),ri=query(tr[x].son[1],mid+1,R);
103             if(SGT::tr[tr[le].num].mid==SGT::tr[tr[ri].num].mid) return tr[le].l<tr[ri].l?le:ri;
104             return SGT::tr[tr[le].num].mid>SGT::tr[tr[ri].num].mid?le:ri;
105         }
106     }
107 }
108 
109 int main(){
110     n=read(); m=read(); MX=1;
111     for(int i=1;i<=60;i++) MX*=2;
112     ST::build(1,1,n); SGT::tr[1]=(SGT::sgt){1,MX,(1+MX)/2,0,0,0,0,1};
113     for(int i=1;i<=n;i++) ST::a[i]=1;
114     while(m--){
115         scanf("%s",st); int k,l=read(),r=read();
116         if(st[0]=='C'){
117             k=read(); 
118             l=ST::a[l]; r=ST::a[r]; SGT::ltst=0; SGT::insert(SGT::root,1,MX,l,r);
119             if(SGT::ltst) {
120                 SGT::tmp[0]=0; SGT::travel(SGT::tr[SGT::ltst].son[SGT::wh]); 
121                 LL L=SGT::tr[SGT::tr[SGT::ltst].son[SGT::wh]].l,R=SGT::tr[SGT::tr[SGT::ltst].son[SGT::wh]].r;
122                 SGT::rebuild(SGT::tr[SGT::ltst].son[SGT::wh],1,SGT::tmp[0],L,R);
123             }
124             ST::modify(1,k,SGT::anew),ST::a[k]=SGT::anew;
125         }else{
126             int ans=ST::query(1,l,r);
127             ans=ST::tr[ans].l;
128             printf("%d\n",ans);
129         }
130     }
131     return 0;
132 }