给定一个长度为N的已知序列A[i](1<=i<=N),要求维护这个序列,能够支持以下两种操作:
1、查询A[i],A[i+1],A[i+2],…,A[j](1<=i<=j<=N)中,升序排列后排名第k的数。
2、修改A[i]的值为j。
所谓排名第k,指一些数按照升序排列后,第k位的数。例如序列{6,1,9,6,6},排名第3的数是6,排名第5的数是9。
输入文件的第一行包含两个整数N和M,分别表示序列的长度为N和有M个操作。
接下来的N个不大于10^9正整数,第i个表示序列A[i]的初始值。
然后的M行,每行为一个操作Q i j k 或者C i j分别表示查询A[i],A[i+1],A[i+2],…,A[j](1<=i<=j<=N)中,升序排列后排名第k的数和修改A[i]的值为j。
对于每个查询,输出一行整数,为查询的结果。测试数据之间不应有空行。
5 3 3 2 1 4 7 Q 1 4 3 C 2 6 Q 2 5 3
3 6
【数据范围】:
20%的数据中,m,n≤100;
40%的数据中,m,n≤1000;
100%的数据中,m,n≤10000。
打一发树套树,表示splay的哪个旋转到根下面的写法好迷。。
树套树常数贼大= =主席树貌似好用不少(还没复习233)
#include
using namespace std;
#define Inc(i,L,r) for(register int i=(L);i<=(r);++i)
#define Red(i,r,L) for(register int i=(r);i>=(L);--i)
const int N = 1e4+10,Maxsiz = N*log2(N)*2;
int n,m,a[N];
struct Splay{
int p[Maxsiz],ch[Maxsiz][2];
int cnt,k[Maxsiz],siz[Maxsiz];
#define Ls(v) ch[v][0]
#define rs(v) ch[v][1]
#define sum(v) siz[v]=siz[Ls(v)]+siz[rs(v)]+1
inline void rotate(int x){
int f=p[x],gf=p[f],tp=rs(f)==x,son=ch[x][!tp];
ch[p[son]=f][tp]=son,sum(f);
ch[p[f]=x][!tp]=f,sum(x);
ch[p[x]=gf][rs(gf)==f]=x;
}
inline void splay(int x,int &rt){
while(p[x]){
if((p[p[x]])&&((rs(p[p[x]])==p[x])==(rs(p[x])==x)))rotate(p[x]);
rotate(x);
}
rt=x;
}
inline void newnode(int x,int v,int Fa){
siz[x]=1;
p[x]=Fa;
k[x]=v;
}
inline void insert(int &x,int v,int Fa,int &root){
if(!x)return newnode(x=++cnt,v,Fa),splay(x,root),void();
insert(ch[x][k[x]x||t[v].rb||t[v].r>1;
build(Lc,L,Mid),build(rc,Mid+1,r);
}
}tr;
inline void init(){
scanf("%d%d",&n,&m);
Inc(i,1,n)scanf("%d",&a[i]);
tr.build(1,1,n);
}
inline void Modify(){
int x,k;scanf("%d%d",&x,&k);
tr.Modify(1,x,0);
a[x]=k;
tr.Modify(1,x,1);
}
inline void Query(){
int ans,L,r,kth;
scanf("%d%d%d",&L,&r,&kth);
for(int x=tr.t[1].rt;x;){
int tmp=tr.Query(1,L,r,sp.k[x]);
if(tmp
补一个主席树,,
和静态版本略有不同(我感觉完全不一样。。),说的可能有点乱,大概是那个意思。
查询区间[l,r],由于主席树的前缀和性质想到树状数组,常规的树状数组直接改点值,我们不过是把点值换成了整棵线段树。
简单地说,就是树状数组套上多棵动态开点的权值线段树。
但是这样写就不满足主席树只加点不删除的性质。。我也很迷~主席树的定义到底是个什么= =
再补:满足前缀和性质的线段树就是主席树~
#include
using namespace std;
const int Maxn=10005;
int n,a[Maxn];
struct SegMent{
struct tree{
int ls,rs,siz;
}t[Maxn*40];int cnt;
inline void modify(int &x,int v,int l,int r,int cmd){
if(l>v||r>1;
modify(t[x].ls,v,l,mid,cmd),modify(t[x].rs,v,mid+1,r,cmd);
}
}seg;
struct BIT{
int root[Maxn];
int q[2][Maxn];
#define lowbit(x) (x)&-(x)
inline void update(int x,int k,int cmd){
for(;x<=n;x+=lowbit(x))seg.modify(root[x],k,0,(1<<30),cmd);
}
inline void getroot(int l,int r){
for(q[0][0]=0;l>0;l-=lowbit(l))q[0][++q[0][0]]=root[l];
for(q[1][0]=0;r>0;r-=lowbit(r))q[1][++q[1][0]]=root[r];
}
inline int sum(bool t){
int ret=0;
for(int i=1;i<=q[t][0];++i)ret+=seg.t[seg.t[q[t][i]].ls].siz;
return ret;
}
inline int query(int l,int r,int k){
if(l==r)return l;
int size=sum(1)-sum(0);
int mid=l+r>>1;
if(size>=k){
for(int i=1;i<=q[0][0];++i)q[0][i]=seg.t[q[0][i]].ls;
for(int i=1;i<=q[1][0];++i)q[1][i]=seg.t[q[1][i]].ls;
return query(l,mid,k);
}else {
for(int i=1;i<=q[0][0];++i)q[0][i]=seg.t[q[0][i]].rs;
for(int i=1;i<=q[1][0];++i)q[1][i]=seg.t[q[1][i]].rs;
return query(mid+1,r,k-size);
}
}
}bit;
int main(){
int m;scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i)scanf("%d",&a[i]);
for(int i=1;i<=n;++i)bit.update(i,a[i],1);
for(int i=1;i<=m;++i){
char c=getchar();while(!isalpha(c))c=getchar();
if(c=='C'){
int x,k;scanf("%d%d",&x,&k);
bit.update(x,a[x],-1);
bit.update(x,a[x]=k,1);
}else {
int l,r,k;scanf("%d%d%d",&l,&r,&k);
bit.getroot(l-1,r);
printf("%d\n",bit.query(0,(1<<30),k));
}
}
return 0;
}