Codeforces Round #619 (Div2) (A - D)

Codeforces Round #619 (Div2)

A
如果在每一位上都有A串与C串相同或者B串与C串相同,那么就可以最终使得A串等于B串;其余情况均不可能满足。

B
记录所有与-1接壤的数字,排序后取中值即可保证填入数字后其差值最小;再用所有相邻非空数的差值来初始化最小初值,两者取较大输出即可。

题目保证一定有一个空位,但是并不满足一定有一个非空位,所以在初始化最小值的时候要注意将其最小值置为0。

C
傻逼题做傻逼了。
在所有长度为n、包含m个101串中找一个使得其至少包含一个1的子串的个数最大的01串,输出子串最多个数。

样例尝试把我向一种奇奇怪怪的构造方法上引导,但是我在n = 10; m = 2的时候发现最好要两个数的间隔均匀才能使得其数值尽可能大,并不是什么中心对称等等的虚假构造办法。不过在写了m元多项式并试图解一个不等式极值的时候发现并不能成功…

最开始我求解子串的办法是枚举右端点,根据最远的1的位置求出左端点可能取的个数。当这种做法屡屡遇挫而过题人数持续增长的时候,我回头重新看自己最开始的解法,发现可以从另一个角度即反面的情况来求解正面。

因为那些空隙的总长度固定,其数量也固定,要使得其总贡献尽可能的小就是尽可能的平摊所有长度给这些空隙。有 m + 1 m + 1 m+1个空隙, l e f t = n − m left = n-m left=nm个位置,记 a = l e f t / ( m + 1 ) a = left / (m + 1) a=left/(m+1), b = l e f t   M O D   ( m + 1 ) b = left \space MOD\space (m + 1) b=left MOD (m+1),那么就有 b b b个空隙有 a + 1 a+1 a+1个位置, m + 1 − b m + 1 - b m+1b个空隙有 a a a个位置,而一段长度为 n n n的区间有 ( n + 1 ) ∗ n / 2 (n + 1) * n / 2 (n+1)n/2个子区间,总数减去这些空隙的所有区间个数即可。


D
水题写慢了。
考虑一种跑步办法可以遍历 n ∗ m n * m nm方格所有的路径:

  • r o w ≠ n − 1 row ≠ n -1 row=n1: m - 1 "R", m - 1, "DUL", 1, "D"
  • r o w = n − 1 row =n-1 row=n1: m - 1 "R", m - 1 "L", n - 1 "U"

对于某些数据情况,可能会出现0 Operatoin的请况,我在场上写的时候挂在了这里来不及改了。其实在每一次存答案的时候都判断一下前面的次数即可,而无需去辛苦地判断 n n n等不等于1这种问题。

ll n, m, k;

struct node{
    ll f;
    string s;
    node(ll x, string _s){
        f = x; s = _s;
    }
};

vector<node> ans;

void push(node a){
    if(a.f != 0) ans.push_back(a);
}


int main(){
//    Fast;
    scanf("%lld%lld%lld", &n, &m, &k);
    
    node moveright = {m - 1, "R"};
    node downup = {m - 1, "DUL"};
    node down = {1, "D"};
    node moveleft = {m - 1, "L"};;
    node moveup = {n - 1, "U"};

    
    if(k > 4 * m * n - 2 * n - 2 * m) puts("NO");
    else{
        puts("YES");
        int row = 0;
        while(k){
            if(k >= m - 1){
                push({moveright});
                k -= m - 1;
            }
            else{
                push({k, "R"});
                k = 0;
            }
            if(row != n - 1){
                if(k >= 3 * (m - 1)){
                    push(downup);
                    k -= 3 * (m - 1);
                }
                else{
                    int left = k % 3;
                    push({k / 3, "DUL"});
                    if(left == 1) ans.push_back({1, "D"});
                    else if(left == 2) ans.push_back({1, "DU"});
                    k = 0;
                }
                if(k >= 1){
                    push(down);
                    k--;
                }
            }
            else{
                if(k >= m - 1){
                    push(moveleft);
                    k -= m - 1;
                }
                else{
                    push({k, "L"});
                    k = 0;
                }
                if(k == n - 1){
                    push(moveup);
                    k = 0;
                }
                else{
                    push({k, "U"});
                    k = 0;
                }
            }
            row++;
        }
        printf("%d\n", (int)ans.size());
        for(auto i: ans){
            printf("%lld ", i.f);
            cout << i.s; printf("\n");
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值