Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include<stdio.h>
- #include<stdlib.h>
- #include<stdbool.h>
- #include<string.h>
- #define N 10
- #define INF 1000000
- int cmp (const void* a, const void* b) {return *(int*)a - *(int*)b;}
- int min(const int a, const int b) {return a < b ? a : b;}
- void swap(int* a, int* b) {static int t; t = *a, *a = *b, *b = t;}
- typedef struct node {
- struct node* next;
- bool isrev; int sz, data[N + 1], srt[N + 1];
- } node;
- typedef node* nptr;
- static inline void extract(nptr cur) {
- if (!cur->isrev) return;
- for (int l = 0, r = cur->sz - 1; l < r; l++, r--)
- swap(&cur->data[l], &cur->data[r]);
- cur->isrev = false;
- }
- static inline void print1(char c[], nptr cur) {
- if (!cur) return;
- printf("%s", c);
- extract(cur), printf("[");
- for (int i = 0; i < cur->sz; i++) {
- printf("%d", cur->data[i]);
- if (i != cur->sz - 1) printf(" ");
- } printf("]\n");
- }
- static inline void print(nptr cur) {
- while (cur) {
- extract(cur), printf("[");
- for (int i = 0; i < cur->sz; i++) {
- printf("%d", cur->data[i]);
- if (i != cur->sz - 1) printf(" ");
- }
- cur = cur->next, printf("] ");
- }
- printf("\n");
- }
- static inline void update(nptr cur) {
- memcpy(cur->srt, cur->data, cur->sz * sizeof(int));
- qsort(cur->srt, cur->sz, sizeof(int), cmp);
- }
- static inline nptr newnode(int arr[], int ql, int qr) {
- nptr ret = (nptr)malloc(sizeof(node));
- ret->sz = qr - ql, ret->next = NULL, ret->isrev = false;
- memcpy(ret->data, &arr[ql], ret->sz * sizeof(int));
- update(ret); return ret;
- }
- static inline void merge(nptr a, nptr b) {
- if (a->sz >= N / 2 || b->sz >= N / 2) {a->next = b; return;}
- extract(a), extract(b);
- memcpy(&a->data[a->sz], b->data, b->sz * sizeof(int));
- static int tmp[N + 1];
- memcpy(tmp, a->srt, a->sz * sizeof(int));
- int aptr = 0, bptr = 0, ptr = 0;
- while (aptr < a->sz && bptr < b->sz)
- if (tmp[aptr] < b->srt[bptr])
- a->srt[ptr++] = tmp[aptr++];
- else
- a->srt[ptr++] = b->srt[bptr++];
- while (aptr < a->sz)
- a->srt[ptr++] = tmp[aptr++];
- while (bptr < b->sz)
- a->srt[ptr++] = b->srt[bptr++];
- a->next = b->next, a->sz += b->sz;
- free(b);
- }
- static inline nptr split(nptr cur, int qi) {
- nptr ret = (nptr)malloc(sizeof(node));
- ret->next = cur->next, cur->next = ret;
- ret->sz = cur->sz - qi, cur->sz = qi, ret->isrev = false;
- extract(cur);
- memcpy(ret->data, &cur->data[qi], ret->sz * sizeof(int));
- update(cur), update(ret);
- return ret;
- }
- static inline nptr build(int arr[], int n) {
- nptr ret = newnode(arr, 0, min(n, N)), cur = ret;
- for (int i = 1; i < (n + N - 1) / N; i++)
- cur->next = newnode(arr, i * N, min(n, (i + 1) * N)), cur = cur->next;
- return ret;
- }
- static inline void insert(nptr root, int qi, int qval) {
- int previ = 0; nptr prevp = NULL, cur = root;
- while (cur && previ + cur->sz <= qi)
- previ += cur->sz, prevp = cur, cur = cur->next;
- if (!cur) {
- cur = (nptr)malloc(sizeof(node));
- cur->next = NULL, cur->sz = 1, cur->isrev = false;
- cur->data[0] = cur->srt[0] = qval;
- } else {
- extract(cur);
- nptr nxt = split(cur, qi - previ);
- if (cur->sz == N)
- nxt->sz++, nxt->data[0] = nxt->srt[0] = qval;
- else {
- cur->data[cur->sz] = cur->srt[cur->sz] = qval;
- for (int i = cur->sz; i > 0 && cur->srt[i] < cur->srt[i - 1]; i--)
- swap(&cur->srt[i], &cur->srt[i - 1]);
- cur->sz++;
- }
- merge(cur, nxt);
- }
- if (prevp) merge(prevp, cur);
- else *root = *cur;
- }
- static inline void erase(nptr root, int qi) {
- int previ = 0; nptr cur = root, prevp = NULL;
- while (cur->next && previ + cur->sz < qi)
- previ += cur->sz, prevp = cur, cur = cur->next;
- extract(cur);
- for (int i = qi - previ; i + 1 < cur->sz; i++)
- swap(&cur->data[i], &cur->data[i + 1]);
- cur->sz--; int p = 0;
- while (cur->srt[p] < cur->data[cur->sz]) p++;
- for (int i = p; i < cur->sz; i++)
- swap(&cur->srt[i], &cur->srt[i + 1]);
- if (prevp) merge(prevp, cur);
- else *root = *cur;
- }
- static inline void reverse(nptr root, int ql, int qr) {
- int previ = 0, bufsz = 0; nptr cur = root, prevp = NULL;
- static nptr buf[1000];
- while (cur && previ + cur->sz < ql)
- previ += cur->sz, prevp = cur, cur = cur->next;
- nptr lptr = cur; cur = split(lptr, ql - previ);
- previ += lptr->sz;
- while (cur && previ + cur->sz <= qr)
- buf[bufsz++] = cur, previ += cur->sz, cur = cur->next;
- nptr rptr = split(cur, qr - previ);
- buf[bufsz++] = cur;
- for (int i = bufsz - 1; i > 0; i--)
- buf[i]->next = buf[i - 1], buf[i]->isrev ^= 1;
- buf[0]->isrev ^= 1, merge(buf[0], rptr);
- merge(lptr, buf[bufsz - 1]);
- if (prevp) merge(prevp, lptr);
- else *root = *lptr;
- }
- static inline int bscount(nptr cur, int qval) {
- int lb = 0, len = cur->sz;
- while (len > 0) {
- int mid = lb + (len >> 1);
- if (cur->srt[mid] < qval)
- lb = mid + 1, len -= (len >> 1) + 1;
- else len >>= 1;
- }
- return lb;
- }
- static inline int count(nptr cur, int ql, int qr, int qval) {
- int ret = 0, previ = 0;
- while (cur && previ + cur->sz <= ql)
- previ += cur->sz, cur = cur->next;
- if (!cur) return ret;
- extract(cur);
- for (int i = ql - previ; i < min(qr - previ, cur->sz); i++)
- ret += (cur->data[i] < qval);
- previ += cur->sz, cur = cur->next;
- if (qr <= previ) return ret;
- while (cur && previ + cur->sz < qr)
- ret += bscount(cur, qval), previ += cur->sz, cur = cur->next;
- if (qr <= previ) return ret;
- extract(cur);
- for (int i = 0; i < qr - previ; i++)
- ret += (cur->data[i] < qval);
- return ret;
- }
- static inline int query(nptr root, int ql, int qr, int qval) {
- int lb = -1e5, len = 2e5 + 5;
- while (len > 0) {
- int mid = lb + (len >> 1);
- if (count(root, ql, qr, mid) <= qval - 1)
- lb = mid + 1, len -= (len >> 1) + 1;
- else len >>= 1;
- }
- return lb - 1;
- }
- int main() {
- int n, q, arr[50005];
- scanf(" %d %d", &n, &q);
- for (int i = 0; i < n; i++)
- scanf(" %d", &arr[i]);
- nptr root = build(arr, n);
- char op[10]; int x, i, l, r, k;
- while (q--) {
- scanf(" %s", op);
- switch (op[0]) {
- case '$':
- print(root); break;
- case 'I':
- scanf(" %d %d", &i, &x);
- insert(root, i - 1, x); break;
- case 'D':
- scanf(" %d", &i);
- erase(root, i - 1); break;
- case 'R':
- scanf(" %d %d", &l, &r);
- reverse(root, l - 1, r); break;
- case 'Q':
- scanf(" %d %d %d", &l, &r, &k);
- printf("%d\n", query(root, l - 1, r, k));
- }
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment