[]
It seems like a super "water problem" and it actually is. It's very proud to find that my code is the fastest and shortest up to now.
[Solution]
Just like the problem which was also called OJ in SCOI2014. Each node on the split-merge tree refers to a segment. This problem is much easier to code than that one of SCOI.
[Code]
Spent too much time on some small mistakes.
#include <cstdio>
#include <cctype>
#include <memory.h>
#include <algorithm>
using namespace std;
#ifdef WIN32
#define getRand() ((rand()<<16)|rand())
#else
#define getRand() (rand())
#endif
int nextInt() {
int d, s = 0;
bool flag = 0;
do {
d = getchar();
if (d == '-')
flag = 1;
} while (!isdigit(d));
do
s = s * 10 + d - 48, d = getchar();
while (isdigit(d));
return flag ? -s : s;
}
typedef pair <int, int> npair;
const int maxn = 80009;
int n, m;
int rt, sz[maxn], ls[maxn], rs[maxn], vl[maxn], vr[maxn], w[maxn], tn;
inline int nodesz(const int& p) {
return vr[p] - vl[p] + 1;
}
int newNode(int l0, int r0) {
tn ++;
vl[tn] = l0;
vr[tn] = r0;
sz[tn] = nodesz(tn);
ls[tn] = 0;
rs[tn] = 0;
w[tn] = getRand();
return tn;
}
inline void update(const int& p) {
sz[p] = sz[ls[p]] + sz[rs[p]] + nodesz(p);
}
int merge(int p, int q) {
if (!p)
return q;
else if (!q)
return p;
else if (w[p] > w[q]) {
rs[p] = merge(rs[p], q);
update(p);
return p;
}
else {
ls[q] = merge(p, ls[q]);
update(q);
return q;
}
}
npair split(int p, int k) {
if (!p)
return npair(0, 0);
else if (sz[ls[p]] == k) {
int q = ls[p];
ls[p] = 0;
update(p);
return npair(q, p);
}
else if (sz[ls[p]] + nodesz(p) == k) {
npair r = npair(p, rs[p]);
rs[p] = 0;
update(p);
return r;
}
else if (sz[ls[p]] < k && sz[ls[p]] + nodesz(p) > k) {
int q = newNode(vl[p] + k - sz[ls[p]], vr[p]);
vr[p] = vl[q] - 1;
sz[p] = nodesz(p);
rs[q] = rs[p];
rs[p] = 0;
update(p);
update(q);
return npair(p, q);
}
else if (sz[ls[p]] > k) {
npair x = split(ls[p], k);
ls[p] = x. second;
update(p);
return npair(x. first, p);
}
else {
npair x = split(rs[p], k - sz[ls[p]] - nodesz(p));
rs[p] = x. first;
update(p);
return npair(p, x. second);
}
}
int kth(int p, int k) {
if (k > sz[p])
return -1;
else if (k > sz[ls[p]] && k <= sz[ls[p]] + nodesz(p))
return vl[p] + k - sz[ls[p]] - 1;
else if (k <= sz[ls[p]])
return kth(ls[p], k);
else
return kth(rs[p], k - sz[ls[p]] - nodesz(p));
}
void ptree(int p, bool flag = 0) {
if (!p)
return;
ptree(ls[p], 1);
if (vl[p] < vr[p])
printf("%d ~ %d ", vl[p], vr[p]);
else
printf("%d ", vl[p]);
ptree(rs[p], 1);
if (!flag)
putchar(10);
}
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
#endif
srand(20338423);
tn = 0;
rt = 0;
n = nextInt();
m = nextInt();
for (int i = 0; i < n; i ++) {
int a = nextInt();
rt = merge(rt, newNode(a, a));
}
while (m --) {
int opt = nextInt();
if (opt == 0) {
int p = nextInt();
int a = nextInt();
int b = nextInt();
npair x = split(rt, p);
x. first = merge(x. first, newNode(a, b));
rt = merge(x. first, x. second);
}
else if (opt == 1) {
int a = nextInt();
int b = nextInt();
npair x = split(rt, b);
npair y = split(x. first, a - 1);
rt = merge(y. first, x. second);
}
else if (opt == 2) {
int p = nextInt();
printf("%d\n", kth(rt, p));
}
}
}