CSP-J 游记


啊,有人就会问我:“i 老师,i 老师,你为什么只写了J的游记呢?S的游记在哪里啊?”

啊,我就会回答:“没资格。”


去年考的太渣了,都没脸写游记,这回写一篇罢(

T1

看了一下题,啪一下就慌了啊,很快啊(主要是因为题目有点长,读了大概 5min 才看懂)。

看懂了之后就觉得:“撕,这不会是个暴力吧?”

于是敲出了一个从 \(l\sim r\) 暴力的算法。

结果发现,诶,为啥第三个附件输出的是 230 呢???

(我把 233 4567 4657 看成了 233 4567 4567

这个愣是搞了我 5min+,旁边的人都开始写 T2 了,还各种庆祝,心态顿时崩了(calm -= 100)。

自己研究了自己代码很久还没发现问题,甚至考场上我小声的说出了:“收钱协会 T1 样例是不是错了啊。”

最后发现是我眼瞎 (╥╯^╰╥)

写了暴力之后发现 \(r-l\) 最大到 \(1e9\),于是敲除了一个从 \(r\sim l\) 枚举和一个小剪枝的代码:

#include

using namespace std;

int n, l, r;

int main() {
    cin >> n >> l >> r;
    int ans = -1;
    for (int i = r;i >= l;i--) {
        ans = max(ans, i % n);
        if (ans == n - 1) break;
    }
    cout << ans << endl;
    return 0;
}

写完就觉得:“T1 稳了稳了,保了个2=”

考后就觉得:“T1 危了危了,不一定2=”

T2

一看题目我就又慌了啊,这 CCF 不讲武德。考前复习的 dp 不给我考,给我考排序?!

再花了 5min- 读完了题,瞬间感觉神清气爽:“这不就是个橙题吗?分分钟切好吧。”

再花了 10min 左右写出了一份时间复杂度爆炸的代码:

#include
#include
#include
using namespace std;

const int maxn = 8010;

int n, q;
int a[maxn];
int a1[maxn];

int main() {
	cin >> n >> q;
	for (int i = 1;i <= n;i++) {
		cin >> a[i];
	}
	while (q--) {
		int opt;
		cin >> opt;
		if (opt == 1) {
			int x, v;
			cin >> x >> v;
			a[x] = v;
		} else if (opt == 2) {
			int x;
			cin >> x;
			for (int i = 1;i <= n;i++) {
				a1[i] = a[i];
			}
			for (int i = 1;i <= n;i++) {
				for (int j = i;j >= 2;j--) {
					if (a1[j] < a1[j - 1]) {
						swap(a1[j], a1[j - 1]);
						if (x == j) {
							x = j - 1;
						}
						else if (x == j - 1) {
							x = j;
						}
					}
				}
			}
			cout << x << endl;
		}
	}
	return 0;
}

信心满满的打开了 sort3.in(还是 sort4.in 记不清了),测了一下大数据。

好家伙,算了 3s+ 才出答案,就离谱。

试图关掉同步流卡常失败。

爬回去看题:

诶,题目中 \(14\sim 16\)\(20\sim 22\)\(a_i\)\(v\) 互不相等,可以干 sort 啊!!!

于是写出了和原来分数一样的优化代码:

#include
#include
#include
using namespace std;

const int maxn = 8010;

int n, q;
int a[maxn];
int a1[maxn];

int main() {
	ios::sync_with_stdio(0); cin.tie(0);
	cin >> n >> q;
	for (int i = 1;i <= n;i++) {
		cin >> a[i];
	}
	while (q--) {
		int opt;
		cin >> opt;
		if (opt == 1) {
			int x, v;
			cin >> x >> v;
			a[x] = v;
		} else if (opt == 2) {
			int x;
			cin >> x;
			for (int i = 1;i <= n;i++) {
				a1[i] = a[i];
			}
			if (n > 1500) {
				sort(a1 + 1, a1 + n + 1);
				for (int i = 1;i <= n;i++) {
					if (a1[i] == x) {
						cout << i << endl;
						break;
					}
				}
			} else {
				for (int i = 1;i <= n;i++) {
					for (int j = i;j >= 2;j--) {
						if (a1[j] < a1[j - 1]) {
							swap(a1[j], a1[j - 1]);
							if (x == j) {
								x = j - 1;
							}
							else if (x == j - 1) {
								x = j;
							}
						}
					}
				}
				cout << x << endl;
			}
		}
	}
	return 0;
}

现在不仅只有 AC 和 TLE 了,还有 RE。


Upd: 2021.10.28

好家伙,竟然可以直接 \(\mathcal{O}(n)\) 枚举一下比 \(a_x\) 的值小的元素个数就是 opt = 2 的答案了!

时间复杂度直接降到了 \(\mathcal{O}(nq)\)。。。

硬生生被题目给误导住了,以为就是得用排序才能解决的,结果几个 for 就给解决了。。。

#include
using namespace std;

const int maxn = 8010;
int n, q;
int a[maxn];

int main() {
    cin >> n >> q;
    for (int i = 1;i <= n;i++) {
        cin >> a[i];
    }
    while (q--) {
        int opt;
        cin >> opt;
        if (opt == 1) {
            int x, v;
            cin >> x >> v;
            a[x] = v;
        }
        if (opt == 2) {
            int x;
            cin >> x;
            int val = a[x];
            int ans = 1;
            for (int i = 1;i < x;i++) {
                if (a[i] <= val) {
                    ans++;
                }
            }
            for (int i = x + 1;i <= n;i++) {
                if (a[i] < val) {
                    ans++;
                }
            }
            cout << ans << endl;
        }
    }
    return 0;
}

诶,也不对啊。\(n\times q=8000\times 2\times10^5=1600000000=\text{十六亿}\)

爆了吧,按理来说是错误的,但是洛谷数据点竟然全过了,有一个点卡了 900ms+ 过的(

CCF 的数据肯定更水,痛失 48pts,要不然我就稳 1= 了 /kk

T3

一看题,哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈或或或或或!哦,我亲爱的大模拟!幸好我考前写了 UVA12412,稳了这波,T3 都能 A,保 1= 了。

赛后发现原来就是个萌萌小模拟,考场上想复杂了

花了将近 10min 读完题,20min+ 调完第一份代码。

测一下第一个样例,Pass。

测一下第二个样例,WA。Σ( ° △ °|||)

Debug 了 10min,没找到问题,决定重构(吸取了模拟赛的经验,新建了个文件重写,不覆盖原文件)。

吼吼吼,写出了第二份代码。

测了一下第一个样例,Pass。

测了一下第二个样例,Pass!!!

测了一下第三个样例,WA!!!( ╯-_-)╯┴—┴

使用了一下 Linux 自带的 diff 对拍一下,有区别的行都会显示出来(别人的对拍程序都太麻烦了)。

发现自己判断 IP 地址是否正确写挂了(就是应该输出 ERR 的时候却输出了 OK)。

调了一下就只剩下第 900 多行有一处不相同,结果是忘了开 long long(

改了一下竟然写出了 AC 代码。

考场上懒得算时间复杂度了,估计爆炸(但是考虑到这种专注于考模拟的题不会特别在意效率吧),没管。

#include
#include
#include
using namespace std;

#define int long long

int strtoi(string str) {
	int ret = 0;
	for (int i = 0;i < (int)str.size();i++) {
		ret *= 10;
		ret += (str[i] - '0');
	}
	return ret;
}

int cnt = 0;
struct computer {
	string a, b, c, d, e;
	int ia, ib, ic, id, ie;
	int type; //1: Server 0: Client
	bool operator == (const computer& x) const{
		if (x.a == a && x.b == b && x.c == c && x.d == d && x.e == e) {
			return true;
		} else {
			return false;
		}
	}
	void clear() {
		a = b = c = d = e = "";
		ia = ib = ic = id = ie = 0;
		type = 0;
	}
} info[1010];

int readret = -1;
void read() {
	readret = -1;
	string opt;
	cin >> opt;
	if (opt == "Server") info[++cnt].type = 1;
	else info[++cnt].type = 0;
	string str, a, b, c, d, e;
	int pt = 0;
	cin >> str;
	int amt1 = 0, amt2 = 0;
	for (int i = 0;i < (int)str.size();i++) {
		if (str[i] == '.') {
			if (amt2 != 0) {
				readret = 0;
				return;
			}
			amt1++;
		}
		if (str[i] == ':') {
			if (amt1 != 3) {
				readret = 0;
				return;
			}
			amt2++;
		}
		if (str[i] == '.' || str[i] == ':') {
			pt++;
		} else {
			if (pt == 0) a += str[i];
			if (pt == 1) b += str[i];
			if (pt == 2) c += str[i];
			if (pt == 3) d += str[i];
			if (pt == 4) e += str[i];
		}
	}
	if (amt1 != 3 || amt2 != 1) readret = 0;
	if ((strtoi(a) == 0 && a != "0") || (strtoi(b) == 0 && b != "0") || (strtoi(c) == 0 && c != "0") || (strtoi(d) == 0 && d != "0") || (strtoi(e) == 0 && e != "0")) {
		readret = 0;
		return;
	}
	info[cnt].a = a, info[cnt].ia = strtoi(a);
	info[cnt].b = b, info[cnt].ib = strtoi(b);
	info[cnt].c = c, info[cnt].ic = strtoi(c);
	info[cnt].d = d, info[cnt].id = strtoi(d);
	info[cnt].e = e, info[cnt].ie = strtoi(e);
	if (strtoi(a) != 0 && a[0] == '0') {
		readret = 0;
		return;
	}
	if (strtoi(b) != 0 && b[0] == '0') {
		readret = 0;
		return;
	}
	if (strtoi(c) != 0 && c[0] == '0') {
		readret = 0;
		return;
	}
	if (strtoi(d) != 0 && d[0] == '0') {
		readret = 0;
		return;
	}
	if (strtoi(e) != 0 && e[0] == '0') {
		readret = 0;
		return;
	}
	return;
}

signed main() {
	freopen("network.in", "r", stdin);
	freopen("network.out", "w", stdout);
	ios::sync_with_stdio(0); cin.tie(0);
	int n;
	cin >> n;
	while (n--) {
		read();
		if (info[cnt].ia > 255 || info[cnt].ib > 255 || info[cnt].ic > 255 || info[cnt].id > 255 || info[cnt].ie > 65535 || readret == 0) {
			cout << "ERR" << endl;
			info[cnt].clear();
			continue;
		}
		if (info[cnt].type == 1) {
			bool flag = true;
			for (int i = 1;i < cnt;i++) {
				if (info[i] == info[cnt] && info[i].type == 1) {
					cout << "FAIL" << endl;
					info[cnt].clear();
					flag = false;
					break;
				}
			}
			if (flag) cout << "OK" << endl;
		} else {
			bool flag = true;
			for (int i = 1;i <= cnt;i++) {
				if (info[i].type == 1 && info[i] == info[cnt]) {
					cout << i << endl;
					flag = false;
					break;
				}
			}
			if (flag) cout << "FAIL" << endl;
		}
	}
	return 0;
}

T4

没看。


总结:

离谱的很,头回 T1 都稳不了。退了吧。

相关