值得紀念的爆零技巧


記錄一下 \(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)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM