5.18周赛

A

显然时间等于走的步数,再观察一下样例2
发现只用用step2,x2,y2记录一个上一次的步数和坐标,再与这一次的step,x,y比较一下,如果(step - step2) < abs(x2 - x) + abs(y2 - y)就标记一个flag = 1;
观察样例3
if((step2 - (x + y)) % 2)也是不行的,也需要标记flag = 1(因为类似于“消磨时间”的走法一定是走偶数步,所以步数与位置的曼哈顿距离必须同奇偶)
边输入边扫,扫完之后看一下flag,如果等于0就输出Yes,等于1就输出No


B

一个最简单的NKOJ上的背包问题1加背包问题2的联合
A,B分别为无限物品,水为仅能用一次的有限物品

v[0] = true;
for(int i = A; i <= T; i ++)if(v[i - A])v[i] = true;
for(int i = B; i <= T; i ++)if(v[i - B])v[i] = true;

for(int i = 0; i <= T; i ++)if(v[i])v[i / 2] = true;
//注意一下,由于这里i是除法,也就是越更新越小,所以for循环从小到大枚举i
//举个栗子:假设f[6] = true,我们将f[3]也标记为true

C

每个人都有一个固定的信息传递对象 —> 每个人的出度都是1
找最少进行几轮—>找最小环
因为每个人的出度都是1,所以不会出现环套环的情况,就可以求最小环
解法:用Tarjan找强连通分量,每一个强连通分量都是一个环(因为题目限制不会有单个点作为强连通分量的存在),在从栈里面弹出点的时候记录一下每一个强连通分量内点的个数,再比较出最小的一个就可以了


D

一道没有人通过的水题orz(当然我是完全不会的)
如果只有一种球:逆序对(凡是交换相邻两个的都是求逆序对) —> 两种球:两个逆序对orz
设白球:1 ~ i个
黑球:1 ~ j个
无论怎么排,一定会占满2n个里面前i + j个位置
所以可以设一个状态f[i][j],表示前i加j个位置中放白球前i个,黑球前j个,所需最少交换次数
决策:i + j号位置放i号白球还是j号黑球
方程:f[i][j] = min{f[i - 1][j] + cntWhite[i][j],f[i][j -1] + cntBlack[i][j]}
cntWhite[i][j] = ① + ②:
①[1,i - 1]白球中,位于i右侧的,都要调整到i左侧(逆序对)
②[1, j]黑球中,位于i右侧的,都要调整到i左侧(逆序对)
cntBlack[i][j] = ③ + ④:
③[1, i]白球中,位于j右侧的,都要调整到j左侧
④[1,j - 1]黑球中,位于j右侧的,都要调整到j左侧
如何求cnt?——暴力枚举!

for(int i = 1; i <= 2 * n; i ++){
    cin>>c>>x;
    if(c == 'w') posw[x] = i;
    else posb[x] = i;
}
//cntW[i][j]
for(int i = 1; i <= n; i ++){
    for(int j = 1; j < i; j ++)
            if(posw[i] < posw[j]) cntW[i][0] ++;
    for(int j = 1; j <= n; j ++){
        cntW[i][j] = cntW[i][j - 1];
        if(posw[i] < posb[j]) cntW[i][j] ++;
    }
}

一般来说数组是存对应位置是哪个球
但是这里我们存的是对应编号是哪个位置
感觉是这辈子自己都想不出来的orz orz orz

猜你喜欢

转载自www.cnblogs.com/qwqq/p/10895750.html