第一题:
题目大意:
给出N个数的数列,如果相邻的两个数加起来是偶数,那么就可以把这两个数消掉,求最多能消掉多少数。
解题过程:
1.先自己手工模拟了几组数据,发现不管消除的顺序如何,最终剩下的是一定的。所以就可以每次任意找两个奇偶性相同的消掉。于是就想到可以用双向链表来模拟。
2.更好的方法:直接用一个栈来模拟,每次加入一个元素,如何和栈顶元素奇偶性一样就弹出栈顶元素。
初始得分100.
第二题:
题目大意:
给出N个数的数列,定义区间[L,R]的权值为AL and AL+1 and AL+2...and AR 。 求是否有权值为0~m的区间。
N<=500000. Ai <=1000000
解题过程:
1.这题真心想不到正解,我就用了很多小优化骗过去了。
优化一:如果从一个左端点向右延伸,已经权值为0了,那么继续延伸下去还是0,就可以停止了。
优化二(来自lsdsjy):如果当前权值的二进制表示只有1个1了,那么就可以停止了(如果这样的话还要判断一下会不会出现0).
其实只有优化1的情况下对于随机生成的数据已经能够秒出了。不过还是不大放心,我又用类此并查集的get_father函数的方法来优化。
优化三:对于每一个元素,记录它右边第一个and 它的结果不等于它本身的数。 这样就可以干掉那些有很多重复的数字连在一起的数据了。
优化四(可能会导致WA):如果确定左端点一直延伸下去很多次,权值都没有变化,那么就退出。至于这个”很多次“具体是多少自己看着办吧,我是80次。
另外说明一下怎么卡掉优化一:只要所有数都是奇数,那么怎么and都不会是0,就退化到O(N2)了。
2.AC算法:从左往右扫描,用一个pre[i]表示当前扫描到的所有数中,二进制表示(从右往左数)第i位为0的最右边的数的位置.然后对于当前扫描的数x,以它为右端点,把所有pre排序,依次and pre数组里的数就可以了。
初始得分100.
第三题:
题目大意:
N个车站之间有M条铁路,这些铁路分别属于不同的公司,不同公司的铁路价格不一样,但都是是随着长度的增加而增加的。
也就是说从A到B的路线可以分成X段,每段都是同一家公司的铁路,每段单独算钱。
求A到B的最小花费。 N<=100,M<=5000,公司的数量<=20
解题过程:
1.这题看起来条件很多,其实没啥好怕的,实际上可以分成3个子问题。
子问题一:求出每家公司长度为x的铁路的花费。
子问题二:求出任意两点间只用公司c的铁路的最短路。
子问题三:计算A到B的最小花费。
2.对于子问题一,根据题目给的公式递推就可以。子问题二是关键,由于数据范围很小,所以可以直接用floyd变形一下来做,加一维表示状态就可以了。对于子问题三,可以用dijkstra来做,只不过转移的时候多来一重循环(枚举到底用的是哪家公司的铁路)。
初始得分70.原因是计算子问题一的数组开的太小了。
总结:
1.许多时候在考场上想不到很靠谱的算法,但是许多算法只要没有碰到恶心的数据都是可以做的,那就尽量先写出来,能拿多少分是多少。比如T2。
2.静态查错的时候不要只盯着最关键的那个函数看,数组的大小,变量名等等都要仔细的检查。
3.尽量在考试结束前10分钟就停止打代码。