Codeforces Round #821 (Div. 2)

A. Consecutive Sum

题目链接:Consecutive Sum

题意:

给定一长度为 n n n的序列 a a a,你可以进行如下操作(两步为一次操作)至多 k k k次 :

  • 选择两数 i i i j j j,其中需满足 i ≡ j ( m o d   k ) i\equiv j(mod\ k) ij(mod k)

  • 交换 a i a_i ai a j a_j aj

操作完毕后,需从序列中选出一段长度为 k k k的连续子序列,求选出的连续子序列的数之和的最大值.

题解:

由于最后选出的连续子序列长度恰好为 k k k,因此序列下标除 k k k余数必定遍历完 0 , 1 , 2 , . . . , k − 1 {0, 1, 2,...,k-1} 0,1,2,...,k1,且对于每一个余数 i i i,我们之多用一次操作便可以从 x % k = i x\% k=i x%k=i x x x中选出最大的一个并交换至 i i i的位置(若 i = 0 i=0 i=0则交换至 k k k),最终复杂度 O ( n ) \Omicron(n) O(n)

code
const ll N=120;

ll T;
ll mx[N];
ll n, k;
ll res;

int main() {
    read(T);
    while (T--) {
        memset(mx, 0, sizeof mx);
        read(n); read(k);
        for (R ll i=1, num; i<=n; i++) {
            read(num);
            chkmax(mx[i%k], num);
        }
        res=0;
        for (R ll i=0; i<k; i++) res+=mx[i];
        writeln(res);
    }
}
B. Rule of League

题目链接: Rule of League

题意:

n n n名选手参加一乒乓球锦标赛,选手编号从 1 1 1 n n n.比赛流程如下:

第一轮 1 1 1号与 2 2 2号先比,败者出局;胜者进入第二轮,与 3 3 3号比,败者出局;胜者进入第三轮与 4 4 4号比…以此类推,保证不存在平局的情况

现信息已知每名选手获胜次数均为 x x x y y y次,问是否存在符合该信息的比赛结果,若存在,输出 n − 1 n-1 n1个数表示每场比赛胜者编号,否则输出 − 1 -1 1.

题解:

注意到在第一轮比赛中 1 1 1 2 2 2比必有一方出局,于是出局的那位胜场为 0 0 0.因此 x , y x, y x,y中必有且只有一个为 0 0 0,否则无解.

x , y x, y x,y中一项为 0 0 0之后,不妨假设 y = 0 y=0 y=0,设共有 a a a个人赢了 x x x次,剩下的人赢 y y y次也即没赢过,由于每次淘汰一个人,最终剩余一人,那么总比赛场数即 a ⋅ x = n − 1 a\cdot x=n-1 ax=n1,因此必须满足 x ∣ n − 1 x|n-1 xn1,否则无解.

无解判定完后,开始构造方案数.从1号或者2号开始,计数器 c n t cnt cnt表示当前胜者胜利几场, n o w now now表示当前胜者是谁.从 1 1 1 n − 1 n-1 n1枚举比赛场数, c n t = x cnt=x cnt=x时将 n o w now now替换为当前场另一选手即可.复杂度 O ( n ) \Omicron(n) O(n)

code
const ll N=120;

ll T;
ll n, x, y;

int main() {
    read(T);
    while (T--) {
        read(n); read(x); read(y);
        if ((x+y==0) || (x*y!=0)) {
            writeln(-1); continue;
        } 
        if (x<y) swap(x, y);
        if ((n-1)%x!=0) {
            writeln(-1); continue;
        }

        for (R ll i=2, now=0, cnt=x; i<=n; i++) {
            if (cnt==x) now=i, cnt=0;
            writesp(now); ++cnt;
        }
        putchar('\n');
    }
}
C. Parity Shuffle Sorting

题目链接:Parity Shuffle Sorting

题意:

给定一长度为 n n n的序列 a a a,你可以进行如下操作(一次操作包含两步)至多 n n n次,目标是使得该队列单调不降.

  • 选定两下标 l < r l<r l<r

  • a l + a r a_l+a_r al+ar为奇数,则令 a r = a l a_r=a_l ar=al;若为偶数,则令 a l = a r a_l=a_r al=ar

    值得注意的是,你无需最小化你的操作次数,仅需保证 n n n次操作内能达成目标即可.可以证明 n n n次内必定能完成目标,故你只需输出你的方案.

思路:

可以注意到,如果我们选定了 l l l r r r,那无论如何选,有一个结果是必然的,即 l l l r r r将会变成同一个值.这个性质既简单又关键.

利用这个性质我们可以先选定 1 1 1 n n n,让 a 1 a_1 a1 a n a_n an的值相等,这时有两种情况 :

  1. a 1 a_1 a1 a n a_n an均为奇数,那遍历 a i ( i = 2 , 3 , . . . n − 1 ) {a_i}(i=2,3,...n-1) ai(i=2,3,...n1),若 a i a_i ai为奇数,那么有 a i + a n a_i+a_n ai+an为偶数,因此选定 i i i n n n可令 a i = a n a_i=a_n ai=an;若 a i a_i ai为偶数,则选定 1 1 1 i i i可令 a i = a 1 a_i=a_1 ai=a1

  2. a 1 a_1 a1 a n a_n an均为偶数,同理分析即可.

运用该算法,我们至多修改 n − 1 n-1 n1个数,且修改每个数均用 1 1 1次操作,故能满足题意.

code
const ll N=1e5+5;

ll T;
ll n, x, y;
ll num[N];

int main() {
    read(T);
    while (T--) {
        read(n);
        for (R ll i=1; i<=n; i++) read(num[i]);
        writeln(n-1);
        if (n==1) continue;
        writesp(1); writeln(n);
        if ((num[1]+num[n])&1) num[n]=num[1];
        else num[1]=num[n];
        for (R ll i=2; i<n; i++) {
            if ((num[1]+num[i])&1) {
                writesp(1); writeln(i);
            }else {
                writesp(i); writeln(n);
            }
        }
    }
}
D1. Zero-One (Easy Version)

题目链接:Zero-One (Easy Version)

题意:

给定两个长度均为 n n n 01 01 01序列 A A A B B B,你可以对序列 A A A进行若干次操作,操作描述如下:

选定两下标 l < r l<r l<r,使得 a l = 1 − a l , a r = 1 − a r a_l=1-a_l, a_r=1-a_r al=1al,ar=1ar.

其中每次操作都有一定花费,若 r = l + 1 r=l+1 r=l+1,则花费为 x x x,否则花费 y y y.保证 x ≥ y x\geq y xy.

试问能否通过操作使 A A A变成 B B B,若可以则输出最小花费,否则输出 − 1 -1 1

思路:

先判断是否有解. 容易发现该操作一次改变两个数,不影响 01 01 01序列的异或和,故若两序列异或和不同,则无解.

然后是求最小花费.若有解,显然需要改变的位置数 n u m num num为偶数.

n u m = 2 num=2 num=2且需改变两数相邻时,不妨设其下标为 v , v + 1 v,v+1 v,v+1,若 x ≤ 2 y x\leq 2y x2y,则直接改变 v v v v + 1 v+1 v+1位置即可.但若 x > 2 y x>2y x>2y,改变一次相邻数不如改变两次间隔数划算,由于序列长至少为 5 5 5,所以我们一定能够找到一个位置 p o s pos pos,使得 p o s pos pos v , v + 1 v, v+1 v,v+1均不相邻.此时先改变 v v v p o s pos pos,再改变 v + 1 v+1 v+1 p o s pos pos即可,代价为 2 y 2y 2y.

n u m = 2 num=2 num=2且两数不相邻,显然代价为 y y y

n u m ≥ 4 num\geq 4 num4时,不妨设需改变位置为 p 1 , p 2 , p 3 , p 4 , . . . , p 2 k − 1 , p 2 k p_1, p_2, p_3, p_4, ..., p_{2k-1}, p_{2k} p1,p2,p3,p4,...,p2k1,p2k,采用贪心的策略,我们进行最少 k k k次操作,第 i i i次操作选择 p i p_{i} pi p k + i p_{k+i} pk+i即可保证每次操作选择两下标不相邻,代价为 y y y.最终最小代价即为 k ∗ y k*y ky

至此,所有情况讨论完毕.

const ll N=3e3+3;
 
ll T;
ll n, x, y;
string s1, s2;
bool s[N], goal[N];
bool sum1, sum2;
ll res;
int main() {
    read(T);
    while (T--) {
        read(n); read(x); read(y);
        cin>>s1>>s2;
        for (R ll i=0; i<n; i++) {
            s[i+1]=s1[i]-'0';
            goal[i+1]=s2[i]-'0';
        }
        chkmin(x, y*2);
        res=0;
        for (R ll i=1; i<=n; i++) {
            if (s[i]^goal[i]) ++res;
        }
        if (res&1) writeln(-1);
        else if (res==0) writeln(0);
        else if (res==2) {
            for (R ll i=1; i<=n; i++) {
                if (s[i]^goal[i]) {
                    if (s[i+1]^goal[i+1]) writeln(x);
                    else writeln(y);
                    break;
                }
            }
        }
        else {
            writeln(res/2*y);
        }
    }
}
D2. Zero-One (Hard Version)
E. Conveyor

爷不会

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值