给定n个数,m次询问,n个数为1--n的排列,每次询问给出了一个区间和k,询问在区间内为第k小的数。
区间内第k小(大)的数可以用SBT来解决,现在m次询问则是动态的,可以用离线处理:将询问区间排序,每次需要插入则插入,需要删除则删除,节省很多时间.......
#include <iostream> #include <algorithm> #include <cmath> #include <cstdio> #include <cstdlib> #include <cstring> #include <string> #include <vector> #include <set> #include <map> #include <queue> #include <stack> #include <climits>//形如INT_MAX一类的 #define MAX 111111 # define MAXM 51111 #define INF 0x7FFFFFFF #define REP(i,s,t) for(int i=(s);i<=(t);++i) #define ll long long #define mem(a,b) memset(a,b,sizeof(a)) #define mp(a,b) make_pair(a,b) #define L(x) x<<1 #define R(x) x<<1|1 # define eps 1e-5 //#pragma comment(linker, "/STACK:36777216") ///传说中的外挂 using namespace std; struct sbt { int l,r,s,key; } tr[MAX]; int top , root; void left_rot(int &x) { int y = tr[x].r; tr[x].r = tr[y].l; tr[y].l = x; tr[y].s = tr[x].s; //转上去的节点数量为先前此处节点的size tr[x].s = tr[tr[x].l].s + tr[tr[x].r].s + 1; x = y; } void right_rot(int &x) { int y = tr[x].l; tr[x].l = tr[y].r; tr[y].r = x; tr[y].s = tr[x].s; tr[x].s = tr[tr[x].l].s + tr[tr[x].r].s + 1; x = y; } void maintain(int &x,bool flag) { if(flag == 0) { //左边 if(tr[tr[tr[x].l].l].s > tr[tr[x].r].s) {//左孩子左子树size大于右孩子size right_rot(x); } else if(tr[tr[tr[x].l].r].s > tr[tr[x].r].s) {//左孩子右子树size大于右孩子size left_rot(tr[x].l); right_rot(x); } else return ; } else { //右边 if(tr[tr[tr[x].r].r].s > tr[tr[x].l].s) { //右孩子的右子树大于左孩子 left_rot(x); } else if(tr[tr[tr[x].r].l].s > tr[tr[x].l].s) { //右孩子的左子树大于左孩子 right_rot(tr[x].r); left_rot(x); } else return ; } maintain(tr[x].l,0); maintain(tr[x].r,1); } void insert(int &x,int key) { if(x == 0) { //空节点 x = ++ top; tr[x].l = tr[x].r = 0; tr[x].s = 1; tr[x].key = key; } else { tr[x].s ++; if(key < tr[x].key) insert(tr[x].l,key); else insert(tr[x].r,key); maintain(x,key >= tr[x].key); } } int del(int &p,int w) { if (tr[p].key==w || (tr[p].l == 0 && w < tr[p].key) || (tr[p].r == 0 && w > tr[p].key)) { int delnum = tr[p].key; if (tr[p].l == 0 || tr[p].r == 0) p = tr[p].l + tr[p].r; else tr[p].key=del(tr[p].l,INF); return delnum; } if (w < tr[p].key) return del(tr[p].l,w); else return del(tr[p].r,w); } int remove(int &x,int key) { int k; tr[x].s --; if(key == tr[x].key || (key < tr[x].key && tr[x].l == 0) || (key > tr[x].key && tr[x].r == 0)) { k = tr[x].key; if(tr[x].l && tr[x].r) { tr[x].key = remove(tr[x].l,tr[x].key + 1); } else { x = tr[x].l + tr[x].r; } } else if(key > tr[x].key) { k = remove(tr[x].r,key); } else if(key < tr[x].key) { k = remove(tr[x].l,key); } return k; } int getmin() { //二叉搜索树找最小值 int x; for(x = root; tr[x].l; x = tr[x].l) ; return tr[x].key; } int getmax() { int x; for(x = root ; tr[x].r; x = tr[x].r) ; return tr[x].key; } int select(int &x,int k) { //求第k小数 int r = tr[tr[x].l].s + 1; if(r == k) return tr[x].key; else if(r < k) return select(tr[x].r,k - r); else return select(tr[x].l,k); } struct node { int l,r,p,id,ans; } qes[MAXM]; int a[MAX]; bool cmp(const node & a, const node & b) { if(a.l == b.l) return a.r < b.r; return a.l < b.l; } bool cmp2(const node &a, const node & b) { return a.id < b.id; } int main() { top = 0; root = 0; int n,m; scanf("%d%d",&n,&m); for(int i=1; i<=n; i++) scanf("%d",&a[i]); for(int i=1; i<=m; i++) { scanf("%d%d%d",&qes[i].l,&qes[i].r,&qes[i].p); qes[i].id = i; } sort(qes+1,qes+m+1,cmp); for(int i=qes[1].l; i<=qes[1].r; i++) { insert(root,a[i]); } qes[1].ans = select(root,qes[1].p); for(int i=2; i<=m; i++) { if(qes[i].l <= qes[i-1].r) { if(qes[i].l > qes[i-1].l) { for(int j=qes[i-1].l; j<qes[i].l; j++) remove(root,a[j]); } if(qes[i].r < qes[i-1].r) { for(int j=qes[i].r+1; j<=qes[i-1].r; j++) remove(root,a[j]); } if(qes[i].r > qes[i-1].r) { for(int j=qes[i-1].r+1; j<=qes[i].r; j++) insert(root,a[j]); } } else { for(int j=qes[i-1].l; j<=qes[i-1].r; j++) { remove(root,a[j]); } for(int j=qes[i].l; j<=qes[i].r; j++) { insert(root,a[j]); } } qes[i].ans = select(root,qes[i].p); } sort(qes+1,qes+m+1,cmp2); for(int i=1; i<=m; i++) printf("%d\n",qes[i].ans); return 0; }