Educational Codeforces Round 76 (Rated for Div. 2)

A - Two Rival Students

题意:共n个人排一排,两个人,位于a,b,相邻位置交换至多x次,最大化abs(a-b)的值。

题解:每次交换至多+1,不能超过n-1。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
 
int main() {
#ifdef KisekiPurin
    freopen("KisekiPurin.in", "r", stdin);
#endif // KisekiPurin
    int t;
    scanf("%d", &t);
    while(t--) {
        int n, x, a, b;
        scanf("%d%d%d%d", &n, &x, &a, &b);
        printf("%d\n", min(n - 1, abs(a - b) + x));
    }
    return 0;
}

B - Magic Stick

题意:给一个数a,有无限次的两种操作:1、若a是偶数,则加上a的一半。2、若a>1,则减去1。问是否可以从x构造出y。

题解:有无限次减法,就看1操作能到达哪里就可以。首先1是不能动的,y<=1。其次,2可以到3,3可以到2,没办法突破到4,所以x=2或x=3时,y<=3。而4可以有4->6->9->8->12->18->27->26->39->...这样无限做下去,所以4以上必有解。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

int main() {
#ifdef KisekiPurin
    freopen("KisekiPurin.in", "r", stdin);
#endif // KisekiPurin
    int t;
    scanf("%d", &t);
    while(t--) {
        ll x, y;
        scanf("%lld%lld", &x, &y);
        bool suc = 0;
        if(x == 1)
            suc = (y <= 1);
        else if(x <= 3)
            suc = (y <= 3);
        else
            suc = 1;
        puts(suc ? "YES" : "NO");
    }
    return 0;
}

C - Dominated Subarray

题意:n(n<=2e5)个数的序列a,ai<=n,找最短的“被支配子区间”,一个子区间被支配有两个条件:1、长度>=2,2、有唯一的众数。

题解:一开始还想二分,二分长度然后验证,还写了一个验证的算法,可以均摊O(1)转移出众数(每次尺取的时候,众数至多变化1)。但是转头一想,小的区间不行大的未必不行的。比如我构造一个这样的:

1
8
2 2 4 4 2 2 4 4

假如一开始二分到4,则验证失败,任意一个子区间的众数都是2和4两个。但最短子区间长度是2。

后来想了一下,是不是最开始考虑的,是否是最短的两个相邻相同元素的差呢?简单证明之后发现的确是这样。

假如最短的两个相邻相同元素为下面的样子:

x,y1,y2,y3,...,yk,x

那么yi互不相等,也当然和x不相等,否则有更短的yi,yj与假设矛盾。则这个区间一定是“被支配子区间”。

但为什么最短“被支配子区间”一定是这样呢?

从x往两边扩展,长度肯定不会更短,而往内收缩,则不会有更短的“被支配子区间”,所以这样的相邻x组成的为被支配子区间的构成元素,长的可以由若干个小的组合得到。在这个算法下n=1不需要特判。注意别被卡memset。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

int n, a[200005];
int pre[200005];

int main() {
#ifdef KisekiPurin
    freopen("KisekiPurin.in", "r", stdin);
#endif // KisekiPurin
    int t;
    scanf("%d", &t);
    while(t--) {
        scanf("%d", &n);
        memset(pre, -1, sizeof(pre[0]) * (n + 1));
        for(int i = 1; i <= n; ++i)
            scanf("%d", &a[i]);

        int minlen = 1e9;
        for(int i = 1; i <= n; ++i) {
            if(pre[a[i]] != -1)
                minlen = min(minlen, i - pre[a[i]] + 1);
            pre[a[i]] = i;
        }
        if(minlen == 1e9)
            minlen = -1;

        printf("%d\n", solve());
    }
    return 0;
}

但是貌似t只有1000,在cf是卡不了memset的样子。

猜你喜欢

转载自www.cnblogs.com/KisekiPurin2019/p/11854682.html