【CodeVS 5032】【省队集训2016 Day5 T1】Play with array

一开始我用分块大法,分成$\sqrt{n}$块,每个块上维护一个Splay,然后balabala维护一下,时间复杂度是$O(n\sqrt{n}logn)$。后来对拍的时候发现比$O(n^2)$的暴力跑得还慢,TA爷说是Splay常数太大2333333

标算是块状链表,什么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!

时间: 2024-10-26 14:08:37

【CodeVS 5032】【省队集训2016 Day5 T1】Play with array的相关文章

[2018湖南省队集训] 6.24 T1 marshland

题面在这里! 一开始感觉像一个类似二分图的最小割,于是成功跑偏2333333 很容易发现一个关键性质,'L'的两个角落在的偶数格 的行(或者列)的奇偶性一定不同.... 于是我们再把偶数格按照行(或者列)的奇偶性再细分成 两类,可以发现只有一个奇数格向旁边的两类偶数格都有空挡的话,才能放下一个L. 所以我们把放L看成网络中的一条流量,要经过三种点,于是对于奇数格拆点限流然后四列点直接跑最大费用最大流就行了.... 因为不用把m个L都放完,所以增广到 dis<0 的时候跳出就好啦.... #inc

JS省队集训记

不知不觉省队集训已经结束,离noi也越来越近了呢 论考前实战训练的重要性,让我随便总结一下这几天的考试 Day 1 T1 唉,感觉跟xj测试很像啊?meet in middle,不过这种题不多测是什么心态? T2 唉,感觉好像做过类似的? T3 唉,怎么是提交答案题…… 感觉前两题都会,信心大增,于是决定先码T2 码了一会,过了第二个样列,还有一个样例?咦怎么过不去? 纠结了一会发现——读错题了,啪啪啪,全写错了……立马就凌乱了 赶快做T1,结果发现meet in middle的空间复杂度好像炸

【UOJ274】【清华集训2016】温暖会指引我们前行 LCT

[UOJ274][清华集训2016]温暖会指引我们前行 任务描述 虽然小R住的宿舍楼早已来了暖气,但是由于某些原因,宿舍楼中的某些窗户仍然开着(例如厕所的窗户),这就使得宿舍楼中有一些路上的温度还是很低. 小R的宿舍楼中有n个地点和一些路,一条路连接了两个地点,小R可以通过这条路从其中任意一个地点到达另外一个地点.但在刚开始,小R还不熟悉宿舍楼中的任何一条路,所以他会慢慢地发现这些路,他在发现一条路时还会知道这条路的温度和长度.每条路的温度都是互不相同的. 小R需要在宿舍楼中活动,每次他都需要从

bzoj 4736 /uoj274【清华集训2016】温暖会指引我们前行 lct

[清华集训2016]温暖会指引我们前行 统计 描述 提交 自定义测试 寒冬又一次肆虐了北国大地 无情的北风穿透了人们御寒的衣物 可怜虫们在冬夜中发出无助的哀嚎 “冻死宝宝了!” 这时 远处的天边出现了一位火焰之神 “我将赐予你们温暖和希望!” 只见他的身体中喷射出火焰之力 通过坚固的钢铁,传遍了千家万户 这时,只听见人们欢呼 “暖气来啦!” 任务描述 虽然小R住的宿舍楼早已来了暖气,但是由于某些原因,宿舍楼中的某些窗户仍然开着(例如厕所的窗户),这就使得宿舍楼中有一些路上的温度还是很低. 小R的

FJ省队集训DAY5 T1

思路:考试的时候打了LCT,自以为能过,没想到只能过80.. 考完一想:lct的做法点数是100W,就算是nlogn也会T. 讲一下lct的做法把:首先如果一条边连接的两个点都在同一个联通块内,那么这条边对答案没有影响,可以忽略,因此,问题变成了每次询问两个点中路径上权值最大的边(这里的权值我们令它为加入这条边的时间),边我们用一个点连接两个端点来表示. 正解:由于是无根树,因此我们用并查集按秩合并,每次把小的加到大的里面去,询问的时候暴力走lct查找最大即可. 1 #include<cstdi

FJ省队集训DAY3 T1

思路:我们考虑如果取掉一个部分,那么能影响到最优解的只有离它最近的那两个部分. 因此我们考虑堆维护最小的部分,离散化离散掉区间,然后用线段树维护区间有没有雪,最后用平衡树在线段的左右端点上面维护最小的id 我讲的貌似不是很清楚.. 还有,蜜汁80分,打死也改不出来.. 1 #include<cstdio> 2 #include<cmath> 3 #include<iostream> 4 #include<cstring> 5 #include<algo

FJ省队集训DAY1 T1

题意:有一堆兔子,还有一个r为半径的圆,要求找到最大集合满足这个集合里的兔子两两连边的直线不经过圆. 思路:发现如果有两个点之间连边不经过圆,那么他们到圆的切线会构成一段区间,那么这两个点的区间一定会有交集,形如s0 s1 e0 e1 同样的,如果是n个点,那就是s0 s1 s2..sn e0 e1 e2.. en 因此,我们枚举那个起始点,然后对于其他点我们按照s排序,对于e做最长上升子序列即可.时间复杂度O(n^2 logn) 1 #include <cstdio> 2 #include

FJ省队集训DAY2 T1

思路:转换成n条三维空间的直线,求最大的集合使得两两有交点. 有两种情况:第一种是以某2条直线为平面,这时候只要统计这个平面上有几条斜率不同的直线就可以了 还有一种是全部交于同一点,这个也只要判断就可以了. 然后我并不能改出来,wa了好多个点 WA的程序: 1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<cstring> 5 #include<algorithm&

HNOI 2016 省队集训日记

第一天 DeepDarkFantasy 从东京出发,不久便到一处驿站,写道:日暮里.  ——鲁迅<藤野先生> 定义一个置换的平方为对1~n的序列做两次该置换得到的序列.已知一个置换的平方,并且这个结果是一个排列,求该置换. 输入第一行一个数n表示排列长度,接下来一行n个数描述排列. 有解则输出一行n个数表示原排列.否则输出一行一个-1. 测试点编号 特征 0~1 n<=10 2~9 n<=1000000 此题有spj. 考试的时候懵逼了,根本没想清就开始乱打. 题解:由题易得每一个