Bzoj 3196 Tyvj 1730 二逼平衡树
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(); }
欢迎来原博客看看 >原文链接<