[ZOJ 2112]Dynamic Rankings
2016-02-26 15:27
246 查看
树套树
外层线段树, 内层平衡树
每次查询的时候需要把区间分解,然后在这些平衡树上二分
外层线段树, 内层平衡树
每次查询的时候需要把区间分解,然后在这些平衡树上二分
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #define N 200001 #define M 1300001 using namespace std; int T, n, m; int a[50001], root ; int sz, c[M][2], size[M], val[M], w[M], rnd[M]; void update(int k){ size[k] = size[c[k][0]] + size[c[k][1]] + w[k]; } void rotate(int &o, int mark){ int cur = c[o][mark]; c[o][mark] = c[cur][mark ^ 1]; c[cur][mark ^ 1] = o; size[cur] = size[o]; update(o); o = cur; } int Newnode(int num){ int now = ++ sz; size[now] = w[now] = 1; c[now][0] = c[now][1] = 0; rnd[now] = rand(); val[now] = num; return now; } void Insert(int &k, int num){ if(k == 0){ k = Newnode(num); return; } size[k] ++; if(val[k] == num){ w[k] ++; return; } if(num < val[k]){ Insert(c[k][0], num); if(rnd[c[k][0]] < rnd[k]) rotate(k, 0); } else{ Insert(c[k][1], num); if(rnd[c[k][1]] < rnd[k]) rotate(k, 1); } } void Delete(int &k, int num){ if(val[k] == num){ if(w[k] > 1){ w[k] --; size[k] --; return; } if(c[k][0] == 0 || c[k][1] == 0) k = c[k][0] + c[k][1]; else if(rnd[c[k][0]] < rnd[c[k][1]]){ rotate(k, 0); Delete(k, num); } else{ rotate(k, 1); Delete(k, num); } return; } Delete(c[k][num > val[k]], num); size[k] --; } int TMP; void build(int id, int l, int r, int x, int num){ Insert(root[id], num); if(l == r)return; int mid = l + r >> 1; if(x <= mid)build(id << 1, l, mid, x, num); else build(id << 1 | 1, mid + 1, r, x, num); } void change(int id, int l, int r, int x, int num, int y){ Delete(root[id], y); Insert(root[id], num); if(l == r)return; int mid = l + r >> 1; if(x <= mid)change(id << 1, l, mid, x, num, y); else change(id << 1 | 1, mid + 1, r, x, num, y); } void find(int id, int num){ if(id == 0)return; if(val[id] <= num){ TMP += size[c[id][0]] + w[id]; find(c[id][1], num); } else find(c[id][0], num); } void Qry(int id, int l, int r, int x, int y, int num){ if(l == x && r == y){ find(root[id], num); return; } int mid = l + r >> 1; if(mid >= y)Qry(id << 1, l, mid, x, y, num); else if(mid < x)Qry(id << 1 | 1, mid + 1, r, x, y, num); else{ Qry(id << 1, l, mid, x, mid, num); Qry(id << 1 | 1, mid + 1, r, mid + 1, y, num); } } int main(){ int test; int x, y, z; scanf("%d", &test); while(test --){ memset(root, 0, sizeof root); sz = 0; scanf("%d%d", &n, &m); for(int i = 1; i <= n; i ++) scanf("%d", &a[i]); for(int i = 1; i <= n; i ++) build(1, 1, n, i, a[i]); for(int i = 1; i <= m; i ++){ char QAQ = getchar(); for(; QAQ < '!'; QAQ = getchar()); if(QAQ == 'C'){ scanf("%d%d", &x, &y); change(1, 1, n, x, y, a[x]); a[x] = y; } else{ scanf("%d%d%d", &x, &y, &z); int l = 0, r = 1000000000; while(l < r){ int mid = l + r >> 1; TMP = 0; Qry(1, 1, n, x, y, mid); if(TMP >= z)r = mid; else l = mid + 1; } printf("%d\n", r); } } } }
相关文章推荐
- DiscuzX3.2禁止登录及注册功能
- 用break/continue语句 百钱百鸡。公鸡5元一只,母鸡3元一只,小鸡1元3只。求100元分别能买多少公鸡、母鸡、小鸡。
- centos or rhel puppet 安装
- ZOJ-3782-Ternary Calculation【11th浙江省赛】
- hadoop 单机安装
- 安装zabbix
- ssh 连接取消yes or no
- 利用redis-sentinel+consul实现redis高可用
- mysql 主备配置 replication
- Java自动化工具Ant的基础使用教程
- tomcat 设置内存和支持中文
- tomcat 与apache 整合
- linux 卸载oracle11g
- http 安装apxs扩展
- linux oracle 解决输入…
- C#关于FTP上的文件操作
- Spring 数据源配置
- oracle11g lsnrctl stat…
- C++学习之内联函数、引用变量、函数重载、函数模板
- keepalived+ipvsadm 安装