值得纪念的爆零技巧
记录一下 \(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\) 出的模拟赛,感觉题目好有质量呀!!
所以考爆了。。
与往常不一样,这次注意到要把数组开大点,不过开的有点过大了。。
就是这个题!!让我打的主席树跟暴力一个分,跟暴力一个分也就算了,蒟蒻的我数组开大了全 \(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