【CodeVS 5032】【省队集训2016 Day5 T1】Play with array
一开始我用分块大法,分成$\sqrt{n}$块,每个块上维护一个Splay,然后balabala维护一下,时间复杂度是$O(n\sqrt{n}logn)$。后来对拍的时候发现比$O(n^2)$的暴力跑得还慢,xxy学长说是Splay常数太大2333333
考试的时候没想到可以在每个块上建一个$10^5$的数组来存储每个数字出现的次数,而是用了常数巨大且复杂度多了一个log的SplayQwQ,发现自己完全没有对空间复杂度的认识啊(┙>∧<)┙へ┻┻
标算是块状链表,什么balabala比较基础地维护,卡着空间开2333333
我把块的大小设为$[\frac{\sqrt{n}}{2},\sqrt{n}×2)$,在codevs上TLE,,,
后来把块的大小改成了$[\sqrt{n},\sqrt{n}×2)$,1s内能轻松跑过。
也许是因为某些玄学的原因吧,,,
#include<cmath> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N = 100000; const int B = 316; const int BB = 632; int in() { int k = 0, fh = 1; char c = getchar(); for(; c < '0' || c > '9'; c = getchar()) if (c == '-') fh = -1; for(; c >= '0' && c <= '9'; c = getchar()) k = (k << 3) + (k << 1) + c - '0'; return k * fh; } struct BLOCK { BLOCK() { nxt = NULL; len = 0; memset(times, 0, sizeof(times)); } BLOCK *nxt; int a[BB + B + 3], times[N + 1], len; }; int cnt = 0; int n; namespace BlockList { BLOCK *head; void Build(BLOCK * t) {head = t;} void split(BLOCK *r) { int rlen = r->len / 2, tlen = r->len - rlen, to = rlen; BLOCK *t = new BLOCK; memcpy(t->a + 1, r->a + rlen + 1, sizeof(int) * tlen); for(int i = 1; i <= tlen; ++i) { ++t->times[t->a[i]]; --r->times[t->a[i]]; } t->len = tlen; r->len = rlen; t->nxt = r->nxt; r->nxt = t; } void merge(BLOCK *r) { BLOCK *t = r->nxt; if (t == NULL) return; int tlen = t->len, to = r->len; memcpy(r->a + to + 1, t->a + 1, sizeof(int) * tlen); for(int i = 1; i <= tlen; ++i) ++r->times[t->a[i]]; r->len += tlen; t = t->nxt; delete r->nxt; r->nxt = t; if (r->len >= BB) split(r); } BLOCK *find(int &k) { BLOCK *t = head; while (k - t->len > 0 && t != NULL) { k -= t->len; t = t->nxt; } return t; } void work(int l, int r) { BLOCK *t = find(r); int num = t->a[r]; --t->times[num]; int tlen = --t->len; for(int i = r; i <= tlen; ++i) t->a[i] = t->a[i + 1]; if (t->len < B) merge(t); t = find(l); for(int i = ++t->len; i > l; --i) t->a[i] = t->a[i - 1]; t->a[l] = num; ++t->times[num]; if (t->len >= BB) split(t); } int query(int l, int r, int k) { BLOCK *tl = find(l), *tr = find(r); int ret = 0; if (tl == tr) { for(int i = l; i <= r; ++i) if (tl->a[i] == k) ++ret; return ret; } else { int lentl = tl->len; for(int i = l; i <= lentl; ++i) if (tl->a[i] == k) ++ret; for(int i = 1; i <= r; ++i) if (tr->a[i] == k) ++ret; for(tl = tl->nxt; tl != tr && tl != NULL; ret += tl->times[k], tl = tl->nxt); return ret; } } } int main() { n = in(); int c = 0, k; BLOCK *tmp = new BLOCK; BlockList::Build(tmp); for(int i = 1; i <= n; ++i) { ++c; if (c > B) { c = 1; tmp->len = B; tmp->nxt = new BLOCK; tmp = tmp->nxt; } k = in(); tmp->a[c] = k; ++tmp->times[k]; } tmp->len = c; int m = in(), op, l, r; while (m--) { op = in(); l = in(); r = in(); if (op == 1) BlockList::work(l, r); else { k = in(); printf("%d\n", BlockList::query(l, r, k)); } } return 0; }
继续颓文化课,期末考试Bless All!
NOI 2017 Bless All