好题啊
首先肯定是线段树 那么考虑我们怎么比较两个数的大小
采用CLJ在重量平衡树和后缀平衡树在信息学奥赛中的应用中提到的标号思想
不妨令每个节点表示一个区间 用区间的中值代表这个数的大小
具体实现是我们不仅要给每个点记录 l,r,mid
还要记录 x y 表示他等价于(x,y)的组合 因为新插入数是没有标号的 只能按定义比较first和second
注意0小于任何数 我没想到好的方法 只能暴力点特殊建一个节点了
替罪羊写的好长 嘤嘤嘤
#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
return *p1++;
}
inline void read(int &x){
char c=nc(),b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}
inline void read(char &x){
for (x=nc();!(x>='A' && x<='Z');x=nc());
}
const int N=600005;
const double oo=1e20;
#define ab 0.75
struct node{
node *ch[2]; int size;
double l,r,mid; pair<node*,node*> val;
bool operator < (const node B){ return mid<B.mid; }
bool operator == (const node B){ return mid==B.mid; }
void update() { size=ch[0]->size+ch[1]->size+1; }
bool bad() { return ch[0]->size>=size*ab+5 || ch[1]->size>=size*ab+5; }
}Mem[N],*root,*null,*zero;
int pnt;
typedef pair<node*,node*> abcd;
bool operator == (abcd A,abcd B){ return *A.first==*B.first && *A.second==*B.second; }
bool operator < (abcd A,abcd B){ return *A.first==*B.first?*A.second<*B.second:*A.first<*B.first; }
inline node *New(abcd key,double l,double r){
node *t=Mem+(++pnt);
t->ch[0]=t->ch[1]=null; t->l=l; t->r=r; t->mid=(l+r)/2; t->val=key; t->size=1;
return t;
}
inline void Init(){
root=null=Mem; null->ch[0]=null->ch[1]=null;
zero=Mem+(++pnt); zero->mid=-1e30;
}
node *lst[N]; int len;
inline void travel(node *p){
if (p==null) return;
travel(p->ch[0]); lst[++len]=p; travel(p->ch[1]);
}
inline node* divide(double l,double r,int lp,int rp){
if (lp>rp) return null;
int mid=(lp+rp)>>1; double m=(l+r)/2;
lst[mid]->ch[0]=divide(l,m,lp,mid-1); lst[mid]->ch[1]=divide(m,r,mid+1,rp); lst[mid]->update();
lst[mid]->l=l; lst[mid]->r=r; lst[mid]->mid=m;
return lst[mid];
}
inline void rebuild(node *&p){
len=0; travel(p); p=divide(p->l,p->r,1,len);
}
inline node **insert(node *&p,double l,double r,abcd key){
if (p==null){ p=New(key,l,r); return &null; }
p->size++;
node **ret;
if (p->val<key)
ret=insert(p->ch[1],p->mid,p->r,key);
else
ret=insert(p->ch[0],p->l,p->mid,key);
if (p->bad()) ret=&p;
return ret;
}
inline void Insert(abcd key){
if (root==null) return void(root=New(key,-oo,oo));
node **p=insert(root,root->l,root->r,key);
if (*p!=null) rebuild(*p);
}
inline node *Find(abcd key){
node *p=root;
while (p!=null){
if (key==p->val) break;
if (key<p->val) p=p->ch[0];
else p=p->ch[1];
}
return p;
}
node *pos[N];
int T[N<<2];
inline int Max(int a,int b){
if (!a||!b) return a+b;
if (*pos[a]==*pos[b]) return min(a,b);
return *pos[a]<*pos[b]?b:a;
}
inline void Build(int x,int l,int r){
if (l==r) return void(T[x]=l); int mid=(l+r)>>1;
Build(x<<1,l,mid); Build(x<<1|1,mid+1,r);
T[x]=Max(T[x<<1],T[x<<1|1]);
}
inline void Modify(int x,int l,int r,int t){
if (l==r) return; int mid=(l+r)>>1;
if (t<=mid) Modify(x<<1,l,mid,t);
else Modify(x<<1|1,mid+1,r,t);
T[x]=Max(T[x<<1],T[x<<1|1]);
}
int ans;
inline void Query(int x,int l,int r,int ql,int qr){
if (ql<=l && r<=qr) return void(ans=Max(ans,T[x]));
int mid=(l+r)>>1;
if (ql<=mid) Query(x<<1,l,mid,ql,qr);
if (qr>mid) Query(x<<1|1,mid+1,r,ql,qr);
}
int n;
int main(){
int Q,l,r,k; char order;
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
Init();
read(n); read(Q);
for (int i=1;i<=n;i++) pos[i]=zero;
Build(1,1,n);
while (Q--){
read(order); read(l); read(r);
if (order=='Q'){
ans=0,Query(1,1,n,l,r),printf("%d\n",ans);
}else if (order=='C'){
read(k);
abcd t=abcd(pos[l],pos[r]);
node *p=Find(t);
if (p==null){
Insert(t),pos[k]=Mem+pnt;
}else
pos[k]=p;
Modify(1,1,n,k);
}
}
return 0;
}