zoukankan      html  css  js  c++  java
  • 【CodeVS 5032】【省队集训2016 Day5 T1】Play with array

    一开始我用分块大法,分成$sqrt{n}$块,每个块上维护一个Splay,然后balabala维护一下,时间复杂度是$O(nsqrt{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
    ", BlockList::query(l, r, k));
    		}
    	}
    	return 0;
    }
    

    继续颓文化课,期末考试Bless All!

  • 相关阅读:
    PHP thinkPHP6.0 部署
    ch09 Sql导入语句
    自定义map 搜索
    MySql 语句
    自定义Mappter
    三袋米的故事
    WPF中实现文件夹对话框(OpenFileDialog in WPF)
    web通过Ajax与WCF交互
    项目管理之我见-程序员程序开发步骤
    存储过程
  • 原文地址:https://www.cnblogs.com/abclzr/p/5597022.html
Copyright © 2011-2022 走看看