Description
您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:
1.查询k在区间内的排名
2.查询区间内排名为k的值
3.修改某一位值上的数值
4.查询k在区间内的前驱(前驱定义为小于x,且最大的数)
5.查询k在区间内的后继(后继定义为大于x,且最小的数)
Input
第一行两个数 n,m 表示长度为n的有序序列和m个操作
第二行有n个数,表示有序序列
下面有m行,opt表示操作标号
若opt=1 则为操作1,之后有三个数l,r,k 表示查询k在区间[l,r]的排名
若opt=2 则为操作2,之后有三个数l,r,k 表示查询区间[l,r]内排名为k的数
若opt=3 则为操作3,之后有两个数pos,k 表示将pos位置的数修改为k
若opt=4 则为操作4,之后有三个数l,r,k 表示查询区间[l,r]内k的前驱
若opt=5 则为操作5,之后有三个数l,r,k 表示查询区间[l,r]内k的后继
Output
对于操作1,2,4,5各输出一行,表示查询结果
Sample Input
9 6
4 2 2 1 9 4 0 1 1
2 1 4 3
3 4 10
2 1 4 3
1 2 5 9
4 3 9 5
5 2 8 5
Sample Output
2
4
3
4
9
HINT
1.n和m的数据范围:n,m<=50000
2.序列中每个数的数据范围:[0,1e8]
3.虽然原题没有,但事实上5操作的k可能为负数
Source
不知道为什么,老是T
线段树维护treap或splay
我的代码真尼玛长,三百多行…………
先挖坑,以后再填
代码(Treap):
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<ctime>
using namespace std;
const int SZ = 1000010;
const int INF = 100000010;
int num[SZ];
int n,m;
struct node{
node *ch[2];
int sz,v,cnt,r;
int cmp(int x)
{
if(x == v) return -1;
return x < v ? 0 : 1;
}
void setc(node *x,int d) { ch[d] = x; }
void maintain()
{
sz = ch[0] -> sz + ch[1] -> sz + cnt;
}
}T[SZ],*null;
struct segnode{
int l,r;
node *root;
}tree[SZ * 4];
void dfs(node *p)
{
if(p == null) return ;
dfs(p -> ch[0]);
printf("%d %d\n",p -> v,p -> cnt);
dfs(p -> ch[1]);
}
int Tcnt = 0;
inline node* newnode(int x)
{
node *k = T + (Tcnt ++);
k -> ch[0] = k -> ch[1] = null;
k -> v = x;
k -> sz = k -> cnt = 1;
k -> r = rand();
return k;
}
inline void rotate(node* &p,int d)
{
node *k = p -> ch[d ^ 1];
p -> ch[d ^ 1] = k -> ch[d];
k -> ch[d] = p;
p -> maintain(); k -> maintain();
p = k;
}
inline int treap_ask_rank(node *p,int x)
{
int ans = 0;
while(p != null)
{
int d = p -> cmp(x);
if(d == -1) return ans + p -> ch[0] -> sz;
if(d == 1) ans += p -> cnt + p -> ch[0] -> sz;
p = p -> ch[d];
}
return ans;
}
inline int treap_ask_num(node *p,int k)
{
while(p != null)
{
int l = p -> ch[0] -> sz + 1;
int r = p -> ch[0] -> sz + p -> cnt;
if(l <= k && k <= r) return p -> v;
if(k > r) k -= r,p = p -> ch[1];
else p = p -> ch[0];
}
}
inline void treap_insert(node* &p,int x)
{
if(p == null)
{
p = newnode(x);
return ;
}
int d = p -> cmp(x);
if(d == -1)
{
p -> cnt ++;
p -> sz ++;
return ;
}
treap_insert(p -> ch[d],x);
if(p -> ch[d] -> r < p -> r) rotate(p,d ^ 1);
p -> maintain();
}
inline void treap_erase(node* &p,int x)
{
if(p == null) return ;
int d = p -> cmp(x);
if(d == -1)
{
if(p -> cnt > 1)
{
p -> cnt --; p -> sz --; return ;
}
if(p -> ch[0] != null && p -> ch[1] != null)
{
int dd = p -> ch[0] -> r < p -> ch[1] -> r ? 0 : 1;
rotate(p,dd ^ 1);
treap_erase(p -> ch[dd ^ 1],x);
}
else
{
if(p -> ch[0] != null) p = p -> ch[0];
else p = p -> ch[1];
}
}
else
treap_erase(p -> ch[d],x);
if(p != null) p -> maintain();
}
inline void treap_change(node* &p,int x,int v)
{
treap_erase(p,x);
/* puts("erase");
printf("%d %d %d\n",tree[pos].l,tree[pos].r,x);
puts("dfs");dfs(tree[pos].root);puts("dfs\n");*/
treap_insert(p,v);
/* puts("insert");
printf("%d %d %d\n",tree[pos].l,tree[pos].r,v);
puts("dfs");dfs(tree[pos].root);puts("dfs\n");*/
}
inline int treap_ask_pre(node *p,int x)
{
int ans = -INF;
while(p != null)
{
if(p -> v < x) ans = p -> v,p = p -> ch[1];
else p = p -> ch[0];
}
return ans;
}
inline int treap_ask_suf(node *p,int x)
{
int ans = INF;
while(p != null)
{
if(p -> v > x) ans = p -> v,p = p -> ch[0];
else p = p -> ch[1];
}
return ans;
}
inline void treap_build(int pos,int l,int r)
{
for(register int i = l;i <= r;++ i)
{
treap_insert(tree[pos].root,num[i]);
}
}
inline void seg_build(int p,int l,int r)
{
tree[p].l = l; tree[p].r = r;
tree[p].root = null;
treap_build(p,l,r);
if(l == r)
{
return ;
}
int mid = (l + r) >> 1;
seg_build(p << 1,l,mid);
seg_build(p << 1 | 1,mid + 1,r);
}
inline int seg_ask_rank(int p,int l,int r,int x)
{
if(l <= tree[p].l && tree[p].r <= r)
{
int ans = treap_ask_rank(tree[p].root,x);
// printf("%d %d %d\n",tree[p].l,tree[p].r,ans);
return ans;
}
int mid = (tree[p].l + tree[p].r) >> 1;
int ans = 0;
if(l <= mid) ans += seg_ask_rank(p << 1,l,r,x);
if(mid < r) ans += seg_ask_rank(p << 1 | 1,l,r,x);
return ans;
}
inline int seg_ask_num(int p,int l,int r,int k)
{
int ll = 0,rr = INF,ans;
while(ll <= rr)
{
int mid = (ll + rr) >> 1;
int tmp = seg_ask_rank(1,l,r,mid) + 1;
if(tmp <= k) ll = mid + 1,ans = mid;
else rr = mid - 1;
}
return ans;
}
inline void seg_change(int p,int pos,int x)
{
treap_change(tree[p].root,num[pos],x);
if(tree[p].l == tree[p].r) return ;
int mid = (tree[p].l + tree[p].r) >> 1;
if(pos <= mid) seg_change(p << 1,pos,x);
else seg_change(p << 1 | 1,pos,x);
}
inline int seg_ask_pre(int p,int l,int r,int x)
{
if(l <= tree[p].l && tree[p].r <= r)
{
int ans = treap_ask_pre(tree[p].root,x);
// printf("hahaha %d %d %d %d\n",ans,x,l,r);
return ans;
}
int ans = -INF;
int mid = (tree[p].l + tree[p].r) >> 1;
if(l <= mid) ans = max(ans,seg_ask_pre(p << 1,l,r,x));
if(mid < r) ans = max(ans,seg_ask_pre(p << 1 | 1,l,r,x));
return ans;
}
inline int seg_ask_suf(int p,int l,int r,int x)
{
if(l <= tree[p].l && tree[p].r <= r)
return treap_ask_suf(tree[p].root,x);
int ans = INF;
int mid = (tree[p].l + tree[p].r) >> 1;
if(l <= mid) ans = min(ans,seg_ask_suf(p << 1,l,r,x));
if(mid < r) ans = min(ans,seg_ask_suf(p << 1 | 1,l,r,x));
return ans;
}
inline void init()
{
null = newnode(-INF);
null -> sz = null -> cnt = 0;
null -> r = -INF;
srand(time(0));
}
inline void scan(int &n)
{
n = 0;
char a = getchar();
bool flag = 0;
while(a < '0' || a > '9') {if(a == '-') flag = 1; a = getchar();}
while('0' <= a && a <= '9') n = (n << 3) + (n << 1) + a - '0',a = getchar();
if(flag) n = -n;
}
int main()
{
// freopen("3196.in","r",stdin); freopen("3196.out","w",stdout);
init();
scan(n),scan(m);
for(int i = 1;i <= n;++ i) scan(num[i]);
seg_build(1,1,n);
while(m --)
{
int opt;
scan(opt);
int l,r,k,pos;
switch(opt)
{
case 1:
scan(l); scan(r); scan(k);
printf("%d\n",seg_ask_rank(1,l,r,k) + 1);
break;
case 2:
scan(l); scan(r); scan(k);
printf("%d\n",seg_ask_num(1,l,r,k));
break;
case 3:
scan(pos); scan(k);
seg_change(1,pos,k);
num[pos] = k;
break;
case 4:
scan(l); scan(r); scan(k);
printf("%d\n",seg_ask_pre(1,l,r,k));
break;
case 5:
scan(l); scan(r); scan(k);
printf("%d\n",seg_ask_suf(1,l,r,k));
break;
}
// dfs(tree[1].root); puts("");
}
return 0;
}
/*
3 9
9 3 6
3 3 9
5 10 1 10 3 1 8
*/
Splay:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int SZ = 1000010;
const int INF = 1000000010;
int num[SZ];
int n,m;
struct node{
node *f,*ch[2];
int sz,v,cnt;
int dir() { return f -> ch[1] == this; }
int cmp(int x)
{
if(x == v) return -1;
return x < v ? 0 : 1;
}
void setc(node *x,int d) { (ch[d] = x) -> f = this; }
void maintain()
{
sz = ch[0] -> sz + ch[1] -> sz + cnt;
}
}T[SZ],*null;
struct segnode{
int l,r;
node *root;
int sum;
}tree[SZ * 4];
void dfs(node *p)
{
if(p == null) return ;
dfs(p -> ch[0]);
printf("%d %d\n",p -> v,p -> cnt);
dfs(p -> ch[1]);
}
int Tcnt = 0;
node* newnode(int x,node *fa)
{
node *k = T + (Tcnt ++);
k -> f = fa;
k -> ch[0] = k -> ch[1] = null;
k -> v = x;
k -> sz = k -> cnt = 1;
return k;
}
void rotate(int pos,node *p)
{
node *fa = p -> f;
int d = p -> dir();
fa -> f -> setc(p,fa -> dir());
fa -> setc(p -> ch[d ^ 1],d); fa -> maintain();
p -> setc(fa,d ^ 1); p -> maintain();
if(fa == tree[pos].root) tree[pos].root = p;
}
void splay(int pos,node *p,node *rt = null)
{
while(p -> f != rt)
{
if(p -> f -> f == rt) rotate(pos,p);
else
{
if(p -> dir() == p -> f -> dir()) rotate(pos,p -> f),rotate(pos,p);
else rotate(pos,p),rotate(pos,p);
}
}
p -> maintain();
}
int splay_ask_rank(node *p,int x)
{
int ans = 0;
while(p != null)
{
int d = p -> cmp(x);
if(d == -1) return ans + p -> ch[0] -> sz;
if(d == 1) ans += p -> cnt + p -> ch[0] -> sz;
p = p -> ch[d];
}
return ans;
}
int splay_ask_num(node *p,int k)
{
while(p != null)
{
int l = p -> ch[0] -> sz + 1;
int r = p -> ch[0] -> sz + p -> cnt;
if(l <= k && k <= r) return p -> v;
if(k > r) k -= r,p = p -> ch[1];
else p = p -> ch[0];
}
}
void splay_erase(int pos,node *p,int x)
{
while(p != null)
{
p -> sz --;
int d = p -> cmp(x);
if(d == -1) { p -> cnt --; break; }
p = p -> ch[d];
}
if(p -> cnt) return ;
splay(pos,p);
if(p -> ch[0] == null) { tree[pos].root = p -> ch[1]; tree[pos].root -> f = null; return ; }
if(p -> ch[1] == null) { tree[pos].root = p -> ch[0]; tree[pos].root -> f = null; return ; }
p = p -> ch[0];
while(p -> ch[1] != null) p = p -> ch[1];
splay(pos,p,tree[pos].root);
p -> ch[1] = tree[pos].root -> ch[1]; p -> ch[1] -> f = p;
p -> f = null; p -> maintain();
tree[pos].root = p;
}
void splay_insert(int pos,node *p,int x)
{
if(tree[pos].root == null) { tree[pos].root = newnode(x,null); return ; }
// printf("rt : %d \n",tree[pos].root -> v);
while(p != null)
{
p -> sz ++;
int d = p -> cmp(x);
if(d == -1) { p -> cnt ++;break; }
// printf("I : %d %d\n",p -> v,d);
if(p -> ch[d] == null)
{
p -> ch[d] = newnode(x,p);
p = p -> ch[d];
break;
}
p = p -> ch[d];
}
splay(pos,p);
}
void splay_change(int pos,node *p,int x,int v)
{
splay_erase(pos,tree[pos].root,x);
// puts("erase");
// printf("%d %d %d\n",tree[pos].l,tree[pos].r,x);
// puts("dfs");dfs(tree[pos].root);puts("dfs\n");
splay_insert(pos,tree[pos].root,v);
// puts("insert");
// printf("%d %d %d\n",tree[pos].l,tree[pos].r,v);
// puts("dfs");dfs(tree[pos].root);puts("dfs\n");
}
int splay_ask_pre(node *p,int x)
{
int ans = -INF;
while(p != null)
{
if(p -> v < x) ans = p -> v,p = p -> ch[1];
else p = p -> ch[0];
}
return ans;
}
int splay_ask_suf(node *p,int x)
{
int ans = INF;
while(p != null)
{
if(p -> v > x) ans = p -> v,p = p -> ch[0];
else p = p -> ch[1];
}
return ans;
}
void splay_build(int pos,int l,int r)
{
for(int i = l;i <= r;i ++)
{
splay_insert(pos,tree[pos].root,num[i]);
}
}
void seg_update(int p)
{
tree[p].sum = tree[p << 1].sum + tree[p << 1 | 1].sum;
}
void seg_build(int p,int l,int r)
{
tree[p].l = l; tree[p].r = r;
tree[p].root = null;
splay_build(p,l,r);
if(l == r)
{
tree[p].sum = num[l];
return ;
}
int mid = (l + r) >> 1;
seg_build(p << 1,l,mid);
seg_build(p << 1 | 1,mid + 1,r);
seg_update(p);
}
int seg_ask_rank(int p,int l,int r,int x)
{
if(l <= tree[p].l && tree[p].r <= r)
{
int ans = splay_ask_rank(tree[p].root,x);
// printf("%d %d %d\n",tree[p].l,tree[p].r,ans);
return ans;
}
int mid = (tree[p].l + tree[p].r) >> 1;
int ans = 0;
if(l <= mid) ans += seg_ask_rank(p << 1,l,r,x);
if(mid < r) ans += seg_ask_rank(p << 1 | 1,l,r,x);
return ans;
}
int seg_ask_num(int p,int l,int r,int k)
{
int ll = 0,rr = INF,ans;
while(ll <= rr)
{
int mid = (ll + rr) >> 1;
int tmp = seg_ask_rank(1,l,r,mid) + 1;
if(tmp <= k) ll = mid + 1,ans = mid;
else rr = mid - 1;
}
return ans;
}
void seg_change(int p,int pos,int x)
{
splay_change(p,tree[p].root,num[pos],x);
if(tree[p].l == tree[p].r) return ;
int mid = (tree[p].l + tree[p].r) >> 1;
if(pos <= mid) seg_change(p << 1,pos,x);
if(mid < pos) seg_change(p << 1 | 1,pos,x);
seg_update(p);
}
int seg_ask_pre(int p,int l,int r,int x)
{
if(l <= tree[p].l && tree[p].r <= r)
{
int ans = splay_ask_pre(tree[p].root,x);
// printf("hahaha %d %d %d %d\n",ans,x,l,r);
return ans;
}
int ans = -INF;
int mid = (tree[p].l + tree[p].r) >> 1;
if(l <= mid) ans = max(ans,seg_ask_pre(p << 1,l,r,x));
if(mid < r) ans = max(ans,seg_ask_pre(p << 1 | 1,l,r,x));
return ans;
}
int seg_ask_suf(int p,int l,int r,int x)
{
if(l <= tree[p].l && tree[p].r <= r)
return splay_ask_suf(tree[p].root,x);
int ans = INF;
int mid = (tree[p].l + tree[p].r) >> 1;
if(l <= mid) ans = min(ans,seg_ask_suf(p << 1,l,r,x));
if(mid < r) ans = min(ans,seg_ask_suf(p << 1 | 1,l,r,x));
return ans;
}
void init()
{
null = newnode(-INF,null);
null -> sz = null -> cnt = 0;
}
void scan(int &n)
{
n = 0;
char a = getchar();
bool flag = 0;
while(a < '0' || a > '9') {if(a == '-') flag = 1; a = getchar();}
while('0' <= a && a <= '9') n = (n << 3) + (n << 1) + a - '0',a = getchar();
if(flag) n = -n;
}
int main()
{
// freopen("3196.in","r",stdin); freopen("3196.out","w",stdout);
init();
scan(n),scan(m);
for(int i = 1;i <= n;++ i) scan(num[i]);
seg_build(1,1,n);
while(m --)
{
int opt;
scan(opt);
int l,r,k,pos;
switch(opt)
{
case 1:
scan(l); scan(r); scan(k);
printf("%d\n",seg_ask_rank(1,l,r,k) + 1);
break;
case 2:
scan(l); scan(r); scan(k);
printf("%d\n",seg_ask_num(1,l,r,k));
break;
case 3:
scan(pos); scan(k);
seg_change(1,pos,k);
num[pos] = k;
break;
case 4:
scan(l); scan(r); scan(k);
printf("%d\n",seg_ask_pre(1,l,r,k));
break;
case 5:
scan(l); scan(r); scan(k);
printf("%d\n",seg_ask_suf(1,l,r,k));
break;
}
// dfs(tree[1].root); puts("");
}
return 0;
}
/*
4 2 2 10 9 4 0 1 1
*/