K、sisth sence
theme:future 与peter两人玩纸牌游戏,游戏规则为给两人发相同数目的牌,每轮每人拿出一张牌比大小,future的牌>Peter则future赢,否则peter赢。而future 可以提前知道peter出牌顺序,问future应怎么安排出牌顺序能使赢的次数最大?若有多种出牌方案,则输出字典序最大的序列。
G、what goes up must come down
theme:给定一个长度为n的数组,问最少交换相邻元素几次可以使数组变成前一部分元素成非减序,后面一部分元素成非增序。
D、shortest common non-subsequence
theme:给定两个由0、1组成的字符串,求最短的不是这两个字符串子序列的序列
B、 Arithmetic Progression
theme:给定一个数组,问从数组中抽取任意数量元素,能构成的最长等差数列长度是多少?
solution:先对数组排序。用map[ pair (a[i], a[j]-a[i] ) ]表示以a[i]为首项,a[j]-a[i]为方差的最长等差数列,可知状态转移方差为
map[ pair (a[i], a[j]-a[i] ) ] = max( map[ pair (a[j], a[j]-a[i] ) ] , 1) + 1。即以第二项为首项,方差一样的最长等差数列。所以dp时从后往前。
C、Emergency Evacation
theme:给定一辆车的座位分布(二维矩阵形式,中间有条过道),有n个乘客,坐在车上不同位置,问最少需要几步他们全都能从exit通道下车。(每次只能往旁边座位或过道移动,或在过道里向后移动)
solution:这题挺巧妙的。如果直接从正面如何下车考虑,会很麻烦,要考虑拥堵情况。但如果从反面转化为上车情况考虑,就是大水题了。将问题转化为:n个人要上车走到各自的位置,一次一个人从通道进去(对应出来时一步一步从exit出),问最少几步。
当一个人上车后,他会往前走到自己座位所在的行,然后到列,所以不会影响下一秒上车的人。所以我们以d[i]算出每个人从上车到走到座位要几步,这几步是不能再少的,同t[i]表示每个人要等几步之后能上车了,可知最终结果为min(d[i]+s[i]),d[i]为定值可求的,而s[i]我们分配的上车顺序(对应原题下车反序)。所以最佳安排方案为d[i]越大的越先进。最后找到min(d[i]+i)即可。
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
#define far(i,n) for(int i=0;i<n;++i)
int a[500005];
int ans[500005];
bool cmp(int a,int b)
{
return a>b;
}
int main()
{
int r,s,p;
cin>>r>>s>>p;
far(i,p)
{
int x,y;
scanf("%d%d",&x,&y);
if(y<=s)
a[i]=r-x+1+s-y+1;
else
a[i]=r-x+1+y-s;
}
// far(i,p)
// cout<<a[i]<<" ";
sort(a,a+p,cmp);
for(int i=0;i<p;++i)
{
ans[i]=a[i]+i;
}
cout<<*max_element(ans,ans+p)<<endl;
}