第一题
【题目及题号】change superoj 978
【题解】
分析一下本题就是要求前面一段连续大写,后面全部小写,然后改变大小写的代价最小。
有两种实现方式。
方式一:f[i][0] 表示当前字符最后为大写
f[i][1] 表示当前字符最后为小写
根据其本身是什么字符及前面的更优状态转移一下即可。
方式二:统计一个从开头到当前字符(含)为小写的数量,从结尾到当前字符(不含)为大写的数量。
然后枚举分界线取min即可。
注意:第二种方式分界线可以为0,所以要从0开始,不然会错。
【考试】
两种方法都写了,然后拍大数据拍出第二种的错,如果一题能够多解时间又够的话最好都写吧。拍一拍减少想不到的情况。
第二题
【题目及题号】count superoj 979
【题解】
题目就是要求一段区间内刚好出现K次的整数K的数量。
方法一:
复杂度为nsqrt(n);
因为在给的数据范围内,最多出现sqrt(n)种可以被统计的数,那么就每次枚举数字统计有效的前缀和。记得每次清空。
(实际是就是优化了空间复杂度的暴力)。
方法二:
复杂度为nlogn
类似采花(bzoj),根据右端点将询问排序。用线段树实现。
定义 last[i]为上一次整数i足够i次的左界位置,pre[i]为上上次的last。
当统计到当前点的时候,分两种情况。
情况一:之前数量不够K,
加入当前字符,如果数量已够K,那么就让[1,last[i]]加1。
情况二:之前数量已够K。
加入当前字符,让区间[pre[i]+1,last[i]]减一,
然后让区间[last[i]+1,q.front()]加1;
最后对于每个询问,如果右界等于当前点就到线段树中去查询左界。将答案打到映射的原序列中即可。
注意事项:
本题中滚动询问的方式应该比较常用。然后要使用queue才行,自己开数组很麻烦,还要估计空间。
不过可以动态编号池,只是实现起来比stl麻烦得多。
方法三:
复杂度(O(nsqrt(n)))
莫队算法。
将询问按左界排序,对于同一左界将其分块,在同一左界中进行暴力扩展即可。
第三题
【题目及题号】road superoj980
【题解】
本题定义cost(i,j)为每次摧毁图中最小边,直到i,j不连通的最小代价。
注意:每条边的摧毁值都不一样。
因为顺着做不太好做,所以可以倒着来。
本题就相当于倒着加边,每次都加最大的,i,j刚好连通前花费的代价为w,那么本题问的代价就是allcost-w。
题目询问 sigma(cost(i,j)) 1 <= i < j <= n;
暴力就可以直接枚举i,j然后倒着做。
考虑冗余,每次枚举i,j的时候有一大部分都是重复的加边。
仔细想想就会发现,每次连通两个连通块,必定都存在一大一小的点对。所以本次连通的点对数量就是size[i]*size[j];
那么这个时候对答案产生的贡献就是(allcost-w)*size[i]*size[j],w不包含当前边的权值。
size用并查集维护,记得每次只对老祖先维护。
【错因】
拼暴力但是暴力有一点问题,第一个点wa掉了。【【【【【第二次】】】】】】】!!!!
尤其注意开long long。