题目链接: Jewel
大致题意
给定n个操作, 操作有如下四种:
Insert X:插入x到序列末尾
query1 L R X:在当前序列中的[l,r]区间找第x小的数
query2 X:在当前序列中,输出X是第几小的数
query3 X:找到当前序列中第X小的数是几。 然后输出的是3种query的和
解题思路
整体二分或主席树
主席树做法
需要将值域离散化, 然后进行正常的主席树查询操作即可.
整体二分做法
需要把操作离线, 然后二分求解即可.
这个题主席树跑的很快, QAQ.
AC代码
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 1; i <= (n); ++i)
using namespace std;
typedef long long ll;
const int N = 2E5 + 10;
vector<int> v;
int find(int x) { return lower_bound(v.begin(), v.end(), x) - v.begin(); }
struct operation {
// 0 a c f NULL
int tp, l, r, k;
// 2 1 n v id
// 3 1 n k id
}; vector<operation> area;
struct node {
int l, r;
int cou;
}t[N << 5];
int root[N], ind;
int build(int a, int c, int tl, int tr, int p) {
int x = ++ind; t[x] = t[p];
t[x].cou += c;
if (tl == tr) return x;
int mid = tl + tr >> 1;
if (a <= mid) t[x].l = build(a, c, tl, mid, t[p].l);
else t[x].r = build(a, c, mid + 1, tr, t[p].r);
return x;
}
int ask(int k, int tl, int tr, int p, int x) {
if (tl == tr) return tl;
int cou = t[t[x].l].cou - t[t[p].l].cou;
int mid = tl + tr >> 1;
if (cou >= k) return ask(k, tl, mid, t[p].l, t[x].l);
return ask(k - cou, mid + 1, tr, t[p].r, t[x].r);
}
int ask_rank(int val, int tl, int tr, int p, int x) {
if (tr <= val) return t[x].cou - t[p].cou;
int mid = tl + tr >> 1;
if (val <= mid) return ask_rank(val, tl, mid, t[p].l, t[x].l);
return t[t[x].l].cou - t[t[p].l].cou + ask_rank(val, mid + 1, tr, t[p].r, t[x].r);
}
int main()
{
int n; int T = 0;
while (~scanf("%d", &n)) {
v.clear(), area.clear(); v.push_back(-0x3f3f3f3f);
ind = 0;
printf("Case %d:\n", ++T);
int len = 0;
rep(i, n) {
char s[10]; scanf("%s", s + 1);
if (s[1] == 'I') {
int val; scanf("%d", &val);
area.push_back({ 0, ++len, val, NULL });
v.push_back(val);
}
else if (s[7] == '1') {
int l, r, k; scanf("%d %d %d", &l, &r, &k);
area.push_back({ 1, l, r, k });
}
else if (s[7] == '2') {
int c; scanf("%d", &c);
area.push_back({ 2, 1, len, c });
v.push_back(c);
}
else {
int k; scanf("%d", &k);
area.push_back({ 3, 1, len, k });
}
}
sort(v.begin(), v.end()); v.erase(unique(v.begin(), v.end()), v.end());
len = v.size() - 1;
ll res1, res2, res3; res1 = res2 = res3 = 0;
for (auto& op : area) {
if (!op.tp) {
int c = find(op.r);
root[op.l] = build(c, 1, 1, len, root[op.l - 1]);
}
else if (op.tp == 1 || op.tp == 3) {
int res = ask(op.k, 1, len, root[op.l - 1], root[op.r]);
if (op.tp == 1) res1 += v[res];
else res3 += v[res];
}
else {
int val = find(op.k);
res2 += ask_rank(val, 1, len, root[op.l - 1], root[op.r]);
}
}
printf("%lld\n%lld\n%lld\n", res1, res2, res3);
}
return 0;
}
/* 整体二分代码 */
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 1; i <= (n); ++i)
using namespace std;
typedef long long ll;
const int N = 1E5 + 10;
int res[N << 1];
struct operation {
// 0 a c f NULL
int tp, l, r, k, id;
// 2 1 n v id
// 3 1 n k id
}; vector<operation> area;
int t[N];
int lowbit(int x) { return x & -x; }
void add(int x, int c) { for (int i = x; i < N; i += lowbit(i)) t[i] += c; }
int ask(int x) {
int res = 0;
for (int i = x; i; i -= lowbit(i)) res += t[i];
return res;
}
int ask(int l, int r) { return ask(r) - ask(l - 1); }
void fact(int l, int r, vector<operation>& q) {
if (q.empty()) return;
if (l == r) {
for (auto& op : q) if (op.tp == 1 || op.tp == 3) res[op.id] = l;
return;
}
int mid = l + r >> 1;
vector<operation> ql, qr;
for (auto& op : q) {
if (!op.tp) {
if (op.r <= mid) add(op.l, op.k), ql.push_back(op);
else qr.push_back(op);
}
else if (op.tp == 1 || op.tp == 3) {
int cou = ask(op.l, op.r);
if (cou >= op.k) ql.push_back(op);
else op.k -= cou, qr.push_back(op);
}
else {
if (mid <= op.k) res[op.id] += ask(op.l, op.r), qr.push_back(op);
else ql.push_back(op);
}
}
for (auto& op : ql) if (!op.tp) add(op.l, -op.k);
fact(l, mid, ql), fact(mid + 1, r, qr);
}
int main()
{
int n; int T = 0;
while (~scanf("%d", &n)) {
printf("Case %d:\n", ++T); area.clear();
int len = 0;
rep(i, n) {
res[i] = 0;
char s[10]; scanf("%s", s + 1);
if (s[1] == 'I') {
int val; scanf("%d", &val);
area.push_back({ 0, ++len, val, 1, NULL });
}
else if (s[7] == '1') {
int l, r, k; scanf("%d %d %d", &l, &r, &k);
area.push_back({ 1, l, r, k, i });
}
else if (s[7] == '2') {
int c; scanf("%d", &c);
area.push_back({ 2, 1, len, c, i });
}
else {
int k; scanf("%d", &k);
area.push_back({ 3, 1, len, k, i });
}
}
fact(0, INT_MAX, area);
ll res1 = 0, res2 = 0, res3 = 0;
for (auto& op : area) {
if (op.tp) {
if (op.tp == 1) res1 += res[op.id];
else if (op.tp == 2) res2 += res[op.id];
else res3 += res[op.id];
}
}
printf("%lld\n%lld\n%lld\n", res1, res2, res3);
}
return 0;
}