经过对csp33、34的研究,我发现第三题大模拟最耗费时间,且拿的部分分也很少,所以做题顺序为12453.
12:40出宿舍门,找自行车,没找到,郁闷,只能走着去考场。
第一题就是简单判断一下即可。
第二题我发现一个字母不断的变,有可能是一条直线,例如a->e->f,然后f就不变了。也有可能是一个环,例如a->b->c->d->e,然后e又变成c。可以对每个字母开一个vector<char >,v[1]='a',v[2]='b',一直到v[4]='e'.这样的话需要做一个判断,如果次数k<=4,那么直接输出v[k]。否则k先减去4,再减去1,相当于此时到了字母c,这个时候k对3取模,输出v[2+k%3].
第一次交95分,t了一个点,常数优化后ac
然后做第四题,我发现前60分就是暴力对每一个基站看能覆盖哪些点,然后两两建边。
当时赛中以为100分做法要离散化一下,又觉得没头绪,就放弃了。
赛后看了知乎大佬那个100分的做法,感觉好巧妙呀。
然后做第五题,先暴力,拿了35分,发现特殊性质A直接就过了。然后做特殊性质B,C。其实道理差不多,这里统一讲。就是维护一个前缀和sum[i],表示1-i不一样的颜色的个数。开一个vector<pair<int ,int > > v[N]来存每一次操作后被操作的和操作的(也就是切下来的)段的所有不连续的区间的左右端点。
例如,123是连续的,而1235是不连续的,这个时候就存[1,3] 和[5].
例如,一开始段为[1,6],我切下[3,4],那么v[1]变成[1,2],[4,5], 新增的 v[2]变成[3,4]。
具体的操作,就是对x[i]那个vector,遍历一下,新开一个temp数组,这个存操作后的x[i]数组,对每一个pair<int ,int >,temp存切割后还剩的部分,这个地方分几种情况讨论,例如切不到、切了左边、切了右边、切了中间。如果切完有剩余,那么temp存一下;如果有被切下来的,那么第i+1个vector存一下切下来的部分。遍历完后v[ x[i] ]=temp.
因为特殊性质c[i-1]<=c[i],所以不同颜色数=颜色段数。
对v[i+1],每个pair<int,int > ,ans+=sum[右端点]-sum[左端点-1],也就是这一段的不同颜色的个数,如果左端点颜色=上一个pair<int ,int >的右端点的颜色,那么ans-=1.
举个例子,对于一次操作完的结果,是区间[1,4],[6,8],1-4段有3种不同颜色,ans+=3.由于1是第一个,不可能和前面段的末尾颜色一样,所以ans不减。而6-8颜色一样,ans+=1.假设6颜色和4颜色一样,那么ans-=1.
当时代码写错了,wa几发,很难受,好在最后过了,拿了65分。
然后第三题,这题题意好难读,写了我一个小时。我当时只想拿30分,一个块,我们要搞清楚从哪开始操作,操作到哪儿,这个要特殊判断,题目中后面说的,我一开始没看到,错了几次,真的很崩溃。题目说要先从块中信息(-、空格开头的行)推出原文件对应的那几行,然后从原文件从前往后找第一个行,使得原文件的那几行和这个推出原文件对应的那几行是一模一样的,这个时候改。
举个例子,原文件:
abcd
fdsf
ereret
wer
tuy
推出原文件对应的那几行:
ereret
wer
那么我们改三四行,按顺序改成加号空格开头的行的内容,1-2、5行不动它
输出答案时,举个例子,假如原文件有十行,从第四行开始,改原文件的四行,那么输出答案时,1-3行原样输出,然后输出4-7行被改成的部分,8-10行原样输出。
这题wa了好几次,好在最后看到了要判断从原文件哪儿开始改,这个判断一加,怒拿三十分。
这个时候还剩一小时,实在不想写了,准备交卷。谁知分数显示325,我就等,过了一会显示355,怒走。
分数100+100+30+60+65=355.