3196: Tyvj 1730 二逼平衡树
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
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
4
3
4
9
思路:
这种题就不需要思路了吧,我几乎是写了一个最麻烦的线段树套Treap(比较经典的树套树),几位机房大佬有写不到100行的树状数组套主席树>这里<
上一下代码,留待日后温习:
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdlib>
#include <cctype>
#define ls p<<1
#define rs p<<1|1
#define O2 __attribute__((optimize("-O2")))
using namespace std;
const int inf = 2147483647;
const int N = 51000;
const int M = 2000010;
int n, m;
int a[N];
class ReadIn {
private:
O2 inline char nc() {
static char buf[100000], *p1, *p2;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
public:
O2 inline int Read() {
int x=0,f=1;char ch=nc();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=nc();};
while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=nc();}
return x*f;
}
O2 inline char getc() {
char ch=nc();
while(isspace(ch))ch=nc();
return ch;
}
}Rd;
class Treap {
int cnt;
struct Tree {
int siz,key,val,v;
int s[2];
}Tr[M];
private:
O2 int Build(int x) {
cnt++;
Tr[cnt].key = rand();
Tr[cnt].val = x;
Tr[cnt].siz = 1;
Tr[cnt].v = 1;
Tr[cnt].s[0] = Tr[cnt].s[1] = 0;
return cnt;
}
O2 void Update(int x) {
Tr[x].siz =
Tr[x].v +
Tr[Tr[x].s[0]].siz +
Tr[Tr[x].s[1]].siz ;
}
O2 void Rotate(int &x,int i) {
int p = Tr[x].s[i];
Tr[x].s[i] = Tr[p].s[i^1];
Tr[p].s[i^1] = x;
Update(x);
Update(p);
x = p;
}
public:
O2 void Insert(int &p, int k) {
if(!p) {
p=Build(k);
}
else if(Tr[p].val==k) {
Tr[p].v++;
}
else {
if(Tr[p].val<k) {
Insert(Tr[p].s[1], k);
if(Tr[Tr[p].s[1]].key>Tr[p].key) {
Rotate(p, 1);
}
}
else {
Insert(Tr[p].s[0], k);
if(Tr[Tr[p].s[0]].key > Tr[p].key) {
Rotate(p, 0);
}
}
}
Update(p);
}
O2 void Del(int &p, int k) {
if(Tr[p].val < k) {
Del(Tr[p].s[1],k);
}
else if(Tr[p].val > k) {
Del(Tr[p].s[0],k);
}
else {
if(Tr[p].v > 1) {
Tr[p].v -- ;
}
else {
if(Tr[p].s[0]*Tr[p].s[1] == 0) {
p = Tr[p].s[0] + Tr[p].s[1];
}
else {
if(Tr[Tr[p].s[0]].key > Tr[Tr[p].s[1]].key) {
Rotate(p, 0);
Del(Tr[p].s[1], k);
}
else {
Rotate(p, 1);
Del(Tr[p].s[0], k);
}
}
}
}
if(p) {
Update(p);
}
}
O2 int Rank(int p, int k) {
if(!p) {
return 0;
}
if(Tr[p].val > k) {
return Rank(Tr[p].s[0], k);
}
else if(Tr[p].val < k) {
return Rank(Tr[p].s[1],k) +
Tr[Tr[p].s[0]].siz +
Tr[p].v;
}
else {
return Tr[Tr[p].s[0]].siz;
}
}
O2 int Pre(int p, int k) {
if(!p) {
return -inf;
}
if(Tr[p].val >= k) {
return Pre(Tr[p].s[0], k);
}
else {
return max(Tr[p].val,
Pre(Tr[p].s[1],k));
}
}
O2 int Suc(int p, int k) {
if(!p) {
return inf;
}
if(Tr[p].val <= k) {
return Suc(Tr[p].s[1], k);
}
else {
return min(Tr[p].val,
Suc(Tr[p].s[0],k));
}
}
}Trp;
class SegmentTree {
private:
struct Tree {
int l, r, root;
int minn;
}Tr[M];
O2 void Build(int l,int r,int p) {
Tr[p].l = l;
Tr[p].r = r;
int i;
for(i=l;i<=r;i++) {
Trp.Insert(Tr[p].root, a[i]);
}
if(l==r) {
Tr[p].minn=a[l];
return ;
}
if(l!=r) {
int mid = (l+r) >> 1;
Build(l,mid,ls);
Build(mid+1,r,rs);
}
Tr[p].minn=min(Tr[ls].minn,Tr[rs].minn);
}
O2 void Change(int p, int x, int c) {
Trp.Del(Tr[p].root,a[x]);
Trp.Insert(Tr[p].root,c);
int &l = Tr[p].l,
&r = Tr[p].r;
if(l==r)
{
Tr[p].minn=c;
return;
}
int mid = (l+r) >> 1;
if(x<=mid) {
Change(ls, x, c);
}
else {
Change(rs, x, c);
}
Tr[p].minn=min(Tr[ls].minn,Tr[rs].minn);
}
O2 int Pre(int l, int r, int p, int k) {
int &ll = Tr[p].l,
&rr = Tr[p].r;
if(ll>r||rr<l) {
return -inf;
}
if(ll>=l&&rr<=r) {
return Trp.Pre(Tr[p].root,k);
}
else {
return max(Pre(l, r, ls, k),
Pre(l, r, rs, k));
}
}
O2 int Suc(int l, int r,int p,int k) {
int &ll = Tr[p].l,
&rr = Tr[p].r;
if(ll>r||rr<l) {
return inf;
}
if(ll>=l&&rr<=r) {
return Trp.Suc(Tr[p].root,k);
}
else {
return min(Suc(l, r, ls, k),
Suc(l, r, rs, k));
}
}
O2 int Rank(int l, int r,int p,int k) {
int &ll = Tr[p].l,
&rr = Tr[p].r;
if(ll>r||rr<l) {
return 0;
}
if(ll>=l&&rr<=r) {
return Trp.Rank(Tr[p].root,k);
}
else {
return Rank(l, r, ls, k)+
Rank(l, r, rs, k);
}
}
O2 int Sum(int l,int r,int k) {
int ll = 0,
rr = (int) 1e9;
while(ll<rr) {
int mid = (ll + rr + 1) >> 1;
if(Rank(l,r,1,mid)<k) {
ll=mid;
}
else {
rr=mid-1;
}
}
return rr;
}
O2 int query(int l,int r,int p,int x,int y) {
if(l>=x&&y>=r) {
return Tr[p].minn;
}
int mid=(l+r)>>1;
int rt=0x3f3f3f3f;
if(x<=mid) {
rt=min(rt,query(l,mid,ls,x,y));
}
if(y>mid) {
rt=min(rt,query(mid+1,r,rs,x,y));
}
return rt;
}
public:
O2 void Solve() {
Build(1, n, 1);
int i,opt,l,r,k,x;
for(i=1;i<=m;i++) {
opt=Rd.Read();
switch (opt) {
case 1 :
l=Rd.Read(),
r=Rd.Read(),
k=Rd.Read();
printf("%d\n",Rank(l,r,1,k)+1);
break;
case 2 :
l=Rd.Read(),
r=Rd.Read(),
k=Rd.Read();
printf("%d\n",Sum(l,r,k));
break;
case 3 :
k=Rd.Read(),
x=Rd.Read();
Change(1,k,x);
a[k] = x;
break;
case 4 :
l=Rd.Read(),
r=Rd.Read(),
k=Rd.Read();
printf("%d\n", Pre(l, r, 1, k));
break;
case 5 :
l=Rd.Read(),
r=Rd.Read(),
k=Rd.Read();
printf("%d\n", Suc(l, r, 1, k));
break;
}
}
}
}Seg;
O2 int main() {
srand(20402);
n=Rd.Read(),
m=Rd.Read();
int i;
for(i=1;i<=n;i++)
a[i]=Rd.Read();
Seg.Solve();
}
欢迎来原博客看看 >原文链接<