题目来源:URAL 1439. Battle with You-Know-Who
题意:开始有数列1, 2, 3, ... L k输出第k大的数 D k删除第k大的数
思路:treap树插入删除的数 每次二分查找第k大的数为mid 查询treap小于等于mid的数有y个 那么mid应该是第mid-y大的数 与k比较 继续二分
#include <cstdio> #include <cstring> #include <cstdlib> #include <algorithm> using namespace std; const int maxm = 100010; int ch[maxm][2], r[maxm], val[maxm], sum[maxm], num[maxm], cnt, root; void Node(int &rt, int x){ rt = ++cnt; ch[rt][0] = ch[rt][1] = 0; r[rt] = rand(); val[rt] = x; if(cnt > 1) { sum[rt] = 1; num[rt] = 1; } else { sum[rt] = 0; num[rt] = 0; } } void maintain(int rt){ sum[rt] = sum[ch[rt][0]]+sum[ch[rt][1]]+num[rt]; } void init() { ch[0][0] = ch[0][1] = 0; r[0] = (1LL<<31)-1; val[0] = 0; sum[0] = 0; cnt = 0; root = 0; Node(root, 2000000001); } void rotate(int &rt, int d){ int k = ch[rt][d^1]; ch[rt][d^1] = ch[k][d]; ch[k][d] = rt; maintain(rt); maintain(k); rt = k; } void insert(int &rt, int x){ if(!rt){ Node(rt, x); return; } else{ if(x == val[rt]) num[rt]++; else { int d = x < val[rt] ? 0 : 1; insert(ch[rt][d], x); if(r[ch[rt][d]] < r[rt]) rotate(rt, d^1); } } maintain(rt); } /*void remove(int &rt, int x){ if(val[rt] == x){ val[rt]--; if(!val[rt]){ if(!ch[rt][0] && !ch[rt][1]) { rt = 0; return; } else{ int d = r[ch[rt][0]] > r[ch[rt][1]] ? 1 : 0; rotate(rt, d); remove(ch[rt][d], x); } else{ } } } else remove(ch[rt][x>val[rt]], x); maintain(rt); }*/ int kth(int rt, int k){ if(rt == 0) return 0; if(val[rt] <= k) return sum[ch[rt][0]]+num[rt]+kth(ch[rt][1], k); return kth(ch[rt][0], k); } int main() { int n, m; while(scanf("%d %d", &n, &m) != EOF) { init(); while(m--) { char s[10]; int x; scanf("%s %d", s, &x); int l = 1, r = n, ans; //printf("****%d\n", kth(root, 10)); while(l < r) { int mid = (l + r) >> 1; int y = kth(root, mid); if(x > mid-y) { l = mid+1; ans = mid+1; } else { r = mid; } //printf("***%d\n", y); } if(s[0] == 'L') { printf("%d\n", l); } else { //int y = kth(root, x); insert(root, l); } } } return 0; }
时间: 2024-10-12 03:48:51