【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!

posted @ 2016-06-18 22:15  abclzr  阅读(251)  评论(0编辑  收藏  举报