HDU 3727 Jewel 主席树
2016-03-31 23:06
260 查看
题意:
一开始有一个空序列,然后有下面四种操作:Insert x在序列尾部加入一个值为\(x\)的元素,而且保证序列中每个元素都互不相同。
Query_1 s t k查询区间\([s,t]\)中第\(k\)小的元素。
Query_2 x查询元素\(x\)的名次
Query_3 k查询整个区间的第\(k\)小值
分析:
首先离线一下所有查询,然后离散化,剩下的都是很经典的主席树操作。#include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long LL; const int maxn = 100000 + 10; const int maxq = 35000 * 3 + 10; const int maxnode = maxn << 5; const int maxcmd = maxn + maxq; int n; char cmd[15]; int type[maxcmd], a[maxcmd], b[maxcmd], c[maxcmd]; int x[maxn], tot; int sz, root[maxn]; int lch[maxnode], rch[maxnode], sum[maxnode]; int update(int pre, int L, int R, int pos) { int rt = ++sz; sum[rt] = sum[pre] + 1; if(L < R) { int M = (L + R) / 2; if(pos <= M) { rch[rt] = rch[pre]; lch[rt] = update(lch[pre], L, M, pos); } else { lch[rt] = lch[pre]; rch[rt] = update(rch[pre], M+1, R, pos); } } return rt; } int query(int l, int r, int L, int R, int k) { if(L == R) return L; int num = sum[lch[r]] - sum[lch[l]]; int M = (L + R) / 2; if(num >= k) return query(lch[l], lch[r], L, M, k); else return query(rch[l], rch[r], M+1, R, k - num); } int Rank(int rt, int L, int R, int x) { if(L == R) return sum[rt]; int M = (L + R) / 2; if(x > M) return sum[lch[rt]] + Rank(rch[rt], M+1, R, x); else return Rank(lch[rt], L, M, x); } int main() { int kase = 1; while(scanf("%d", &n) == 1) { tot = 0; for(int i = 0; i < n; i++) { scanf("%s", cmd); scanf("%d", a + i); if(!cmd[6]) { type[i] = 0; x[tot++] = a[i]; } else type[i] = cmd[6] - '0'; if(type[i] == 1) scanf("%d%d", b + i, c + i); } sort(x, x + tot); int cnt = 0; sz = 0; LL ans[3]; for(int i = 0; i < 3; i++) ans[i] = 0; for(int i = 0; i < n; i++) { if(type[i] == 0) { cnt++; int pos = lower_bound(x, x + tot, a[i]) - x + 1; root[cnt] = update(root[cnt-1], 1, tot, pos); } else if(type[i] == 1) { int q = query(root[a[i]-1], root[b[i]], 1, tot, c[i]); ans[0] += x[q - 1]; } else if(type[i] == 2) { int pos = lower_bound(x, x + tot, a[i]) - x + 1; ans[1] += Rank(root[cnt], 1, tot, pos); } else { int q = query(0, root[cnt], 1, tot, a[i]); ans[2] += x[q - 1]; } } printf("Case %d:\n", kase++); for(int i = 0; i < 3; i++) printf("%lld\n", ans[i]); } return 0; }
相关文章推荐
- leetcode 31. Next Permutation
- ubuntu server 改变phpmyadmin的默认访问路径
- DTS、杜比2.0、杜比5.1、AC3各是什么意思
- Add Two Numbers(OC版)
- 浅谈栈帧(一)
- ListView优化之图片的三级缓存(LruCache)
- IOS UIScrollView——用法详解
- LinearLayout, FrameLayout,RelativeLayout 布局案例
- 牛客网每日打卡-Java基础-20160331
- DRY
- 每天一篇python:时间日期篇
- 【Codeforces659D】Bicycle Race【向量叉积】
- DatePickerDialog日期选择器的使用
- 仿百度壁纸客户端(二)——主页自定义ViewPager广告定时轮播图
- 快速排序
- 仿百度壁纸客户端(二)——主页自定义ViewPager广告定时轮播图
- jar7
- for 循环嵌套 while 的神奇问题
- leetcode_147 Insertion Sort List
- 浅谈css背景