抉择吧!在序列上!
序列上的决策问题的分析
Summary
这类问题,通常情况下是给一连串的事件,在这些事件中我们拥有着决策权!然后要求最优化XXX
日常被这种题卡成苟,好弱!太弱!
写点东西来通过一些栗子分析一下应对这类问题的魔术回路吧。
一、贪心
常见操作
- 正着扫一遍
- 倒着扫一遍
- 维护前缀最大值
- 维护前缀和
- 按XXX排序,重写cmp
- 拿优先队列维护XXX,拿栈模拟什么的
我们不妨从如下几个角度来对这个问题进行分析
1. 栈
最常见的问题就是括号匹配啦!
我们通常会这样采访每一个元素:“您是愿意进栈,还是愿意带走栈顶的元素呢?”
栗子1:2018 TCO1B 250
类似于括号匹配直接模拟就好。
栗子2:DuiZi and ShunZi
南宁邀请赛被这个题虐哭。
从小到大排序,从前往后扫,如果能和前面配出顺子或对子的话,pop,否则push,因为不这么做话,不会更优。
栗子3: CF949A
拿set维护的栈?雾。
拿set,lower_bound一下就好了查询下一个0,或者下一个1的位置就好了。
2. 优先队列
如果是维护前缀最大值,我们不断更新max变量就好了。
但如果我们取走最大值后,需要用第2大的值,取走第2大的值后,需要第3大的值.....
那么我们就要用到优先队列了。
栗子1:Gym100247I
因为前面的状态会影响后面的决策,所以我们可以考虑DP,然后就可以投降了。会Unlimited TLE & MLE Work
我们不妨以一个拖延症患者的心态考虑这个问题。
从前往后扫。
- 能不被砸死,那我们去high!高兴!去玩!
- 如果很不幸,被砸死了,那我们回到过去把最可恶的石头搞掉,然后继续high!高兴!去玩!
3. 重写cmp
这种问题,往往是给我们一大堆东西,然后问我们先施展哪个,后施展哪个。才能使得XXX最优。
如果存在全序关系,重写cmp稳如老狗。
栗子
一支军队有n
场战役要打,第i
场战役,需要x[i]
人参战,会牺牲y[i]
人,可以随意决定战役顺序,问军队至少需要多少人。
很基本,对吧!把第i场战役和第j场战役拿出来放入一个结界。看看先施展i好,还是先施展j好。
先i
, max(x[j]+y[i],x[i])
先j
, max(x[i]+y[j],x[j])
4. 区间问题
姿势1:排序
一般是
- 按左端点从小到大排序。
- 按右端点从小到大排序。
Warning:第二关键字特别注意啦!!!!
姿势2:差分
其实就是,把一个区间拆成+1,-1 (a[l]++, a[r+1]--
)
这和括号匹配很相似哎!
栗子1 2017 EC-Final J
solution: 3,4,5可以拼出长度>=5的任意连续段,类似于括号匹配,我们从前往后扫一遍,对于一个右括号,我们只能和2个位置及以前的左括号匹配。
栗子2 ARC088B
solution:
if k != k+1:
ans = max(ans,max(k,n-k))
话说,这好像和差分没什么关系吖!单想这个题的时候蜜汁联想到上一题,还是把这题放这吧。
考虑相邻且不相等的两个数字,我们一定能翻转[1,k]
或[k+1,n]
使他们相等。
二、DP
1. 背包
一个特征:好多个ITEM,排成一排,然后我们决定,每个物品,拿?还是不拿?
2. 翻锁
a) 一个简单的栗子
一次操作我们可以给一个区间同时+1,把{0,0,0......,0}变成{a[1],a[2].....a[n]}最少需要几步操作。
solution:dp[i]=dp[i-1]+max(a[i]-a[i-1],0)
这岂止是不简单,这东西难搞成智障!!!
注意一下,我们把0翻成2,可以正着转2下,可以正着转12下.........,所以在设计状态的时候我们应该把位移考虑进去。
hint1:
一步操作可以理解成,[+1......]-1
或者[-1......]1
hint2:
区间之间的关系,只能是相离,或者包含,不能是相交。
我们用dp[i][j][2]
,表示前i位全施展好了,第i位,总位移为j,方向为正还是反。的最小操作数。
如果第i
位和第i-1
位方向相同,那么转移姿势与上一题一样。
否则,第i位的花费等于第i
位的位移。