值得纪念的爆零技巧

记录一下 \(zcxxxxx\) 的爆零技巧,以供大家一起爆零 \(QWQ\)

2022.11.14

都快要考试了我还挂大分,我就是个菜鸡


考场上用了 set,堆,pair套pair,pbds,还有直接存下标比较

然后发现 pair 套 pair 是跑的最快的。

所以以后结构体内需要按某种方式排序的时候,可以试一试pair套pair,但是只适用于元素较少的情况,因为太繁琐……

具体实践了一下:

set 和 pair

bool check2 (int mid) {
	int k = mid, v = ans1;
	set <pair <int, pair <int, int> > > s;
	for (int i = 1; i <= n; ++ i) {
		if (v >= a[i].a) {
			s.insert (make_pair (a[i].b, make_pair (a[i].d, a[i].c)));
			while (i + 1 <= n && a[i + 1].a <= v) {
				++ i;
				s.insert (make_pair (a[i].b, make_pair (a[i].d, a[i].c)));
			}
		}
		while (s.size ()) {
			int x = s.begin ()->first, y = s.begin ()->second.first, z = s.begin ()->second.second;
			s.erase (s.begin ());
			if (x <= k) k += y, v += z;
			else return 0;
		}
	} return 1;
}

struct node1 {
	int a, b, c;
	bool operator < (const node1 &x) const {
		if (x.a == a) {
			return x.b < b;
		}
		return x.a < a;
	}
};
bool check2 (int mid) {
	ll k = mid, v = ans1;
	priority_queue <node1> s;
	for (int i = 1; i <= n; ++ i) {
		if (v >= a[i].a) {
			s.push ((node1){a[i].b, a[i].d, a[i].c});
			while (i + 1 <= n && a[i + 1].a <= v) {
				++ i;
				s.push ((node1){a[i].b, a[i].d, a[i].c});
			}
		}
		while (s.size ()) {
			int x = s.top ().a, y = s.top ().b, z = s.top ().c;
//			cout << x <<" ";
			s.pop ();
			if (x <= k) k += y, v += z;
			else return 0;
		}
	} return 1;
}

堆 存下标

struct node1 {
	int a, b, c;
	bool operator < (const node1 &x) const {
		if (x.a == a) {
			return x.b < b;
		}
		return x.a < a;
	}
};
bool check2 (int mid) {
	ll k = mid, v = ans1;
	priority_queue <node1> s;
	for (int i = 1; i <= n; ++ i) {
		if (v >= a[i].a) {
			s.push ((node1){a[i].b, a[i].d, a[i].c});
			while (i + 1 <= n && a[i + 1].a <= v) {
				++ i;
				s.push ((node1){a[i].b, a[i].d, a[i].c});
			}
		}
		while (s.size ()) {
			int x = s.top ().a, y = s.top ().b, z = s.top ().c;
//			cout << x <<" ";
			s.pop ();
			if (x <= k) k += y, v += z;
			else return 0;
		}
	} return 1;
}


手残数组开小了,全 RE 了。

写了 O(kn+km) 的,然后开了207*507,手真的残。


写了一个特别繁琐的做法。

说实话我都不确定跑出来时个啥东西,以后不要用奇奇怪怪的求解方法,不需要特殊处理的东西尽量不用,宁可多想一会也不要急着去写。



看了一眼,觉得思路很简单,然后看了看时间,还剩了一个小时啊,我就决定,不打暴力了,写正解,于是没写出来……于是寄了整场比赛。

就到最后的时候,我是手指冰凉的感觉,打着打着手就突然僵那了,然后看了看还有20分钟,决心一定能挑出来,然后没调出来。

以后一定不能莽了……

看见这种大数据结构,一定先写个暴力。

一个小时打了个这个玩意

# include <bits/stdc++.h>
using namespace std;
const int D = 2e5 + 7;
int n, m;
int v[D], a[D], b[D];
int tv[D << 2], ta[D << 2], tb[D << 2], tgo[D << 2];
int lzyv[D << 2], lzya[D << 2], lzyb[D << 2], lzyt[D << 2];
void pushup (int now) {
	tv[now] = tv[now << 1] + tv[now << 1 | 1];
	ta[now] = ta[now << 1] + ta[now << 1 | 1];
	tb[now] = tb[now << 1] + tb[now << 1 | 1];
	tgo[now] = tgo[now << 1] + tgo[now << 1 | 1];
}
void build (int now, int l, int r) {
	if (l == r) {
		tv[now] = v[l];
		ta[now] = a[l];
		tb[now] = b[l];
		tgo[now] = a[l] * b[l];
		return;
	}
	int mid = l + r >> 1;
	build (now << 1, l, mid);
	build (now << 1 | 1, mid + 1, r);
	pushup (now);
}
void pushdown (int now, int l, int r) {
	if (lzyv[now]) {
		int mid = l + r >> 1;
		int ll = l, lr = mid, rl = mid + 1, rr = r;
		lzyv[now << 1] += lzyv[now];
		lzyv[now << 1 | 1] += lzyv[now];
		tv[now << 1] += (lr - ll + 1) * lzyv[now];
		tv[now << 1 | 1] += (rr - rl + 1) * lzyv[now];
	}
//	if (l == r) {
//		cout << l <<" " << lzya[now] << "||\n";
//	}
	if (lzya[now]) {
		int mid = l + r >> 1;
		int ll = l, lr = mid, rl = mid + 1, rr = r;
		lzya[now << 1] += lzya[now];
		lzya[now << 1 | 1] += lzya[now];
		ta[now << 1] += (lr - ll + 1) * lzya[now];
		ta[now << 1 | 1] += (rr - rl + 1) * lzya[now];
		tgo[now << 1] += lzya[now] * tb[now << 1];
		tgo[now << 1 | 1] += lzya[now] * tb[now << 1 | 1];
	}
	if (lzyb[now]) {
		int mid = l + r >> 1;
		int ll = l, lr = mid, rl = mid + 1, rr = r;
		lzyb[now << 1] += lzyb[now];
		lzyb[now << 1 | 1] += lzyb[now];
		tb[now << 1] += (lr - ll + 1) * lzyb[now];
		tb[now << 1 | 1] += (rr - rl + 1) * lzyb[now];
		tgo[now << 1] += lzyb[now] * ta[now << 1];
		tgo[now << 1 | 1] += lzyb[now] * ta[now << 1 | 1];
	}
	if (lzyt[now]) {
		int mid = l + r >> 1;
		int ll = l, lr = mid, rl = mid + 1, rr = r;
		lzyt[now << 1] += lzyt[now];
		lzyt[now << 1 | 1] += lzyt[now];
		tv[now << 1] += tgo[now << 1] * lzyt[now << 1];
		tv[now << 1 | 1] += tgo[now << 1 | 1] * lzyt[now << 1 | 1];
	}
}
void update (int now, int l, int r, int L, int R, int x) {
	pushdown (now, l, r);
	if (l == r) {
		lzyv[now] += x;
		tv[now] += x * (r - l + 1);
		return;
	}
	int mid = l + r >> 1;
	if (L <= mid) update (now << 1, l, mid, L, R, x);
	if (R >= mid + 1) update (now << 1 | 1, mid + 1, r, L, R, x);
	pushup (now);
}
void updatea (int now, int l, int r, int L, int R, int x) {
	pushdown (now, l, r);
	if (l == r) {
		ta[now] += x * (r - l + 1);
		tgo[now] += x * tb[now];
		lzya[now] += x;
		return;
	}
	int mid = l + r >> 1;
	if (L <= mid) updatea (now << 1, l, mid, L, R, x);
	if (R >= mid + 1) updatea (now << 1 | 1, mid + 1, r, L, R, x);
	pushup (now);
}
void updateb (int now, int l, int r, int L, int R, int x) {
	pushdown (now, l, r);
	if (l == r) {
		tb[now] += x * (r - l + 1);
		tgo[now] += x * ta[now];
		lzyb[now] += x;
		return;
	}
	int mid = l + r >> 1;
	if (L <= mid) updateb (now << 1, l, mid, L, R, x);
	if (R >= mid + 1) updateb (now << 1 | 1, mid + 1, r, L, R, x);
	pushup (now);
}
int query (int now, int l, int r, int L, int R) {
	pushdown (now, l, r);
	if (l == r) return tv[now];
	int mid = l + r >> 1, re = 0;
	if (L <= mid) re += query (now << 1, l, mid, L, R);
	if (R >= mid + 1) re += query (now << 1 | 1, mid + 1, r, L, R);
	return re;
}
void go (int now, int l, int r, int L, int R, int x) {
	pushdown (now, l, r);
	if (l == r) {
		lzyt[now] += x;
		tv[now] += tgo[now] * x;
		return;
	}
	int mid = l + r >> 1;
	if (L <= mid) go (now << 1, l, mid, L, R, x);
	if (R >= mid + 1) go (now << 1 | 1, mid + 1, r, L, R, x);
	pushup (now);
}
int main () {
	freopen ("drink.in","r",stdin);
	freopen ("drink.out","w",stdout);
	cin >> n >> m;
	for (int i = 1; i<= n; ++ i) cin >> v[i] >>a[i] >> b[i];
	build (1, 1, n);
//	cout << tgo[1] << "\n";
	int op, t, l, r, x, las = 0;
	for (int i = 1; i <= m; ++ i) {
		cin >> op >> t;
		go (1, 1, n, 1, n, t - las);
//		cout << tv[1] << " " << tgo[1] << "\n";
//		for (int j = 1; j <= n; ++ j) {
//			cout << query (1, 1, n, j, j) << " ";
//		} puts ("|");
		if (op == 1) {
			cin >> l >> r;
			cout << query (1, 1, n, l, r) << "\n";
		}
		if (op == 2) {
			cin >> l >> r >> x;
			updatea (1, 1, n, l, r, x);
		}
		if (op == 3) {
			cin >> l >> r >> x;
			updateb (1, 1, n, l, r, x);
		}
		if (op == 4) {
			cin >> l >> r >> x;
			update (1, 1, n, l, r, x);
		}
		las = t;
	}
}

/*

5 5
1 2 3
4 5 6
7 8 9
10 11 12
13 14 15
2 1 1 3 2
1 3 2 3
3 4 1 4 -3
4 5 1 3 -5
1 6 1 5

*/

最后实在是调不出来了,干脆,单点修改单点查询吧,成绩出来了,测了一下,竟然没 TLE 的有七个点,就是没取模,一分没有。

2022.10.26

读错题了,相同的东西换了两种方式跑了两边。

好粗心啊。

就是这两个东西。

我以为不一样呢,式子写的那么麻烦#¥……%

要注意认真读题了。

2022.10.25

今天用了 \(string\) ,正解的思路,跑不过暴力,好强啊…

以后少用 \(string\) 了。

2022.10.23

考了 \(rk3\) ,空间开大点就 \(rk1\)

T1 :

我是真没想到我打的 \(20\) 分的代码能跑 \(40\) 分……

T3 :

算着复杂度貌似只能跑 \(40\) 分的。但是其实能跑到 \(60\) 分。

大意了。

总结一下就是,只要算好了空间,可以开大点,给程序多点机会多跑几个点。真的就有时候与想的不同,排除复杂度算错的原因,可能有数据水之类的情况发生。所以开大空间。

2022.9.25

下午打了 luogu 的 NOIP 模拟赛,然后几个二臂错误没了 175 pts,心痛/(ㄒoㄒ)/~~

T1:

然后挂了100 pts

T2:
没认真读题,空间小了一半,-75pts

然后 T3 给了个样例分,然后我就拿了个样例分。

总分:10 pts,预计分:185 pts

rank 3 没了。

跳楼了,

2022.4.20

\(nyy\)\(szt\) 出的模拟赛,感觉题目好有质量呀!!

所以考爆了。。

与往常不一样,这次注意到要把数组开大点,不过开的有点过大了。。

CF765F Souvenirs

就是这个题!!让我打的主席树跟暴力一个分,跟暴力一个分也就算了,蒟蒻的我数组开大了全 \(MLE\)\(o(╥﹏╥)o\)

一开始打完了主席树,调着调着大样例,发现跑了一会不动弹了,,我就以为是数组开小了的事儿,于是傻不拉几的把原本开的正好的数组改成了五六个 \(1e7\) 的数组。。然后继续调,还是没过,但是后来忘了把数组开了那么大了,也没惜管,然后就超空间了。。

所以以后一定不要把开的过大或者过小了。

放一下原本的代码,给个警醒。。

/**
 *	author: zcxxxxx
 *	creater: 2022.3.30
**/
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int A = 1e2 + 7;
const int B = 1e3 + 7;
const int C = 1e4 + 7;
const int D = 1e5 + 7;
const int E = 1e6 + 7;
const int INF = 1e18;
const int mod = 1e9 + 7;
inline int read() {
	int x = 0, f = 1; char c = getchar();
	while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
	while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
	return x * f;
}
int n, m, cnt, tot;
struct node {
	int l, r, val, siz;
}t[E * 10];
int a[E * 10], b[E * 10], c[E * 10], d[E * 10];
int root[E * 10];
inline void work() {
	sort(b + 1, b + 1 + n);
	tot = unique(b + 1, b + 1 + n) - b - 1;
	for(int i = 1; i <= n; ++ i) {
		a[i] = lower_bound(b + 1, b + tot + 1, a[i]) - b;
		d[a[i]] = c[i];
	}
}
inline void build(int &now, int l, int r) {
	now = ++ cnt;
	if(l == r) {
		t[now].val = d[l];
		return;
	}
	int mid = l + r >> 1;
	build(t[now].l, l, mid);
	build(t[now].r, mid + 1, r);
}
inline void insert(int las, int &now, int l, int r, int x) {
	now = ++ cnt;
	t[now] = t[las];
	t[now].siz ++;
	if(l == r) {
		return;
	}
	int mid = l + r >> 1;
	if(x <= mid) insert(t[las].l, t[now].l, l, mid, x);
	else insert(t[las].r, t[now].r, mid + 1, r, x);
}
int last, mn;
inline void query(int las, int now, int l, int r) {
	if(!t[now].siz) return;
	if(mn == 0) return;
	if(l == r) {
		if(t[now].siz > 1) mn = min(mn, 0ll);
		else mn = min(mn, abs(t[now].val - last)), last = t[now].val;
		return;
	}
	int mid = l + r >> 1;
	int sl = t[t[now].l].siz - t[t[las].l].siz;
	int sr = t[t[now].r].siz - t[t[las].r].siz;
	if(sl) query(t[las].l, t[now].l, l, mid);
	if(sr) query(t[las].r, t[now].r, mid + 1, r);
}
signed main() {
	n = read();
	for(register int i = 1; i <= n; ++ i) {
		a[i] = b[i] = c[i] = read();
	}
	work();
	build(root[0], 1, tot);
	for(register int i = 1; i <= n; ++ i) {
		insert(root[i - 1], root[i], 1, tot, a[i]);
	}
	m = read();
	for(register int l, r, i = 1; i <= m; ++ i) {
		l = read(), r = read();
		mn = INF, last = -INF;
		query(root[l - 1], root[r], 1, tot);
		printf("%lld\n", mn);
	}
	return 0;
}

2022.2.27

又考试,从中午起来就感觉不对劲,身体软绵绵的……

果然,下午又倒数。。。

竟然把橙题黄题都做错了,第三题大暴力还没打出来(;へ:)

做的是2015年的day1,做过的人都知道,除了T3都很水……

T1 是一道小模拟,虽然小吧,但是我好像是因为太困了,整整调了一节课 \(QAQ\),最后发现读错题了,“右上”读成“左上”了……

T2 一看就是个找最小环,我直接激动地把 \(tarjan\) 就打上了呀,感觉很对。

最后一交,\(T1\) \(T2\) 都只有 \(50\),看了一下代码,\(T1\) 数组开小了……

做题的时候迷迷糊糊的看了一眼数据范围,然后打上了const int A = 47就完了 (ノД`)

应该开 \(n ^ 2\)

\(T2\) 我的 \(tarjan\) 函数里初始化low[u] = dfn[u] = u就很无语……

我怎么这么没状态,有大佬来指点一下该怎么避免吗( Ĭ ^ Ĭ )

2022.2.13

寒假集训结束前,举行了一次模拟赛。。

然后……考了倒一

主要问题出在 T1 上,本来不算T1,T2T3 合起来能考第二来,然后 \(T1\) 爆了……,为什么呢,请观摩如下两份代码:

/*
Worker:zcxxxxx
*/
#include <bits/stdc++.h>
using namespace std;
const int maxn = 100 + 7;
const int INF = 0x7fffffff;
inline int read() {
	int x = 0, f = 1; char c = getchar();
	while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
	while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
	return x * f;
}
int n;
string s;
int num[maxn];
int base = 233333;

int main() {
	n = read();
	for(int i = 1; i <= n; i++) {
		cin >> s;
		int len = s.size();
		for(int j = 0; j < len; j++) {
			num[j + 1] = s[j] - 'a' + 1;
			num[j + 1] *= base;
		}
		for(int j = 1; j < len; j++) num[j] = (num[j] + num[len]) % 26 + 97, cout << (char)num[j];
	}
	return 0;
}

and

/*
Worker:zcxxxxx
*/
#include <bits/stdc++.h>
using namespace std;
const int maxn = 100 + 7;
const int INF = 0x7fffffff;
inline int read() {
	int x = 0, f = 1; char c = getchar();
	while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
	while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
	return x * f;
}
int n;
string s;
int num[maxn];
int base = 233333;

int main() {
	n = read();
	for(int i = 1; i <= n; i++) {
		cin >> s;
		int len = s.size();
		for(int j = 0; j < len; j++) {
			num[j + 1] = s[j] - 'a' + 1;
			num[j + 1] *= base;
		}
		for(int j = 1; j < len; j++) num[j] = (num[j] + num[len]) % 26 + 97, cout << (char)num[j];
		cout << "\n";
	}
	return 0;
}

一看好像没啥区别,当我上午考完抑郁了一中午后,回到机房,打开测试点准备调代码时,发现输出和输入混到一行了……

才发现原来是没输出换行,直接疯掉。

最后幸亏有 \(npy\) ,才缓下来

直接少了 \(100\) 分啊,以后一定要检查清楚呜呜呜o(╥﹏╥)o

(持续更新ing)
posted @ 2022-02-27 20:09  zcxxxxx  阅读(265)  评论(7编辑  收藏  举报