思维训练

K-Bag(2020牛客多校第6场K)

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
OJ:牛客

题目描述

A sequence is called k k k-bag, if and only if it is put in order by some (maybe one) permutations of 1 1 1 to k k k. For example, 1,2,3,2,1,3,3,2,1 is a valid 3 3 3-bag sequence.
Roundgod is not satisfied with k k k-bag, so she put forward part- k k k-bag, which is a contiguous subsequence of k k k-bag.
Wcy wants to know if the sequence of length n n n is a part- k k k-bag sequence.

输入描述:

The first line contains one integer T   ( 1 ≤ T ≤ 20 ) T\ (1\le T\le 20) T (1T20), denoting the number of test cases. Then T T T test cases follow.
The first line of each test case contains two integers n , k   ( 1 ≤ n ≤ 5 ⋅ 1 0 5 , 1 ≤ k ≤ 1 0 9 ) n,k\ (1\le n \le 5 \cdot 10^5,1\le k \le 10^9) n,k (1n5105,1k109).
The second line of each test case contains nn integers indicate the sequence.
It is guaranteed that ∑ n ≤ 2 ⋅ 1 0 6 \sum n \le 2\cdot 10^6 n2106, the values of the sequence are between 1 1 1 and 1 0 9 10^9 109.

输出描述:

One line of each test case, if the sequence is a part- k k k-bag sequence, print “YES”, otherwise print “NO”.

输入

1
8 3
2 3 2 1 3 3 2 1

输出

YES

题意

给你一个长度为 n n n,数值范围为 [ 1 , k ] [1,k] [1,k] 的一个数字串,判断这个数字串是否是若干个 1 − k 1-k 1k 的排列的子串。

样例解释:
2,3 2,1,3 3,2,1

题解

由一个 l e n len len 数组,保存第 i i i 位开始的,互不相同的排列的最大长度。

显然,两个相同元素中间一定有一个分割点把数字串划分成两个区间表示两个不同的排列。

那么第一个分割点一定在 [ 0 , l e n [ 0 ] ) [0,len[0]) [0,len[0])

由于k的存在,第一个分割点的位置也要满足 [ 0 , k ) [0,k) [0,k)

所以我们在 [ 0 , m i n ( l e n [ 0 ] , k ) ) [0,min(len[0],k)) [0,min(len[0],k)) 里枚举第一个分割点,之后只需要往后跳着判断就行了。

如果跳的位置 p p p l e n [ p ] len[p] len[p] k k k(最后一个区间长度可以小于 k k k ,因为不一定是完整的排列),说明这个区间可以和前面我们分割的区间一致;否则就意味着分割点不能把数字串分割成若干个排列。

代码

// #pragma GCC optimize(2)
#include <bits/stdc++.h>
#define m_p make_pair
#define _for(i, a) for(register int i = 0, lennn = (a); i < lennn; ++i)
#define _rep(i, a, b) for(register int i = (a), lennn = (b); i <= lennn; ++i)
#define outval(a) cout << "Debuging...|" << #a << ": " << a << "\n"
#define mem(a, b) memset(a, b, sizeof(a))
#define mem0(a) memset(a, 0, sizeof(a))
#define fil(a, b) fill(a.begin(), a.end(), b);
#define scl(x) scanf("%lld", &x)
#define sc(x) scanf("%d", &x)
#define pf(x) printf("%d\n", x)
#define pfl(x) printf("%lld\n", x)
#define abs(x) ((x) > 0 ? (x) : -(x))
#define PI acos(-1)
#define lowbit(x) (x & (-x))
#define dg if(debug)
#define nl(i, n) (i == n - 1 ? "\n":" ")
#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))
using namespace std;
typedef long long LL;
// typedef __int128 LL;
typedef unsigned long long ULL;
typedef pair<int, int> p_i;
typedef pair<LL, LL> p_l;
const int maxn = 500005;
const int maxm = 1000005;
const int maxp = 30;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1000000007;
const double eps = 1e-8;
const double e = 2.718281828;
int debug = 0;

inline LL read() {
    LL x(0), f(1); char ch(getchar());
    while (ch<'0' || ch>'9') { if (ch == '-') f = -1; ch = getchar(); }
    while (ch >= '0'&&ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
    return x * f;
}

int n, k, a[maxn], len[maxn], b[maxn], pre[maxn];

void init() {

}

void sol() {
    init();
    _for(i, n) a[i] = read();
    // 离散化
    _for(i, n) b[i] = a[i];
    sort(b, b + n);
    int l = unique(b, b + n) - b;
    _for(i, n) a[i] = lower_bound(b, b + l, a[i]) - b;
    // 从第i个开始最长的只出现一次的元素的区间的长度
    _for(i, n + 1) pre[i] = 0, len[i] = 0;
    int p = 0;
    _for(i, n) {
        while(!pre[a[p]] && p < n) ++pre[a[p++]];
        --pre[a[i]], len[i] = p - i;
    }
    dg _for(i, n) printf("%d%s", len[i], nl(i, n));
    int ans = 0;
    for(int i = 0; i < min(k, len[0] + 1); ++i) {
        int f = 1;
        for(int j = i; j < n; j += k) {
            if(j + len[j] >= n) break;
            else if(len[j] != k) {
                f = 0;
                break;
            }
        }
        if(f) {
            ans = 1;
            break;
        }
    }
    printf("%s\n", ans ? "YES":"NO");
}

int main() {
    //ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    debug = 1;
#endif
    time_t beg, end;
    if(debug) beg = clock();

    int T = read();
    _for(i, T) {
        n = read(), k = read();
        sol();
    }

    if(debug) {
        end = clock();
        printf("time:%.2fs\n", 1.0 * (end - beg) / CLOCKS_PER_SEC);
    }
    return 0;
}

D. Extreme Subtraction

time limit per test: 2 seconds
memory limit per test: 256 megabytes
Judge: CodeForces

You are given an array a a a of n n n positive integers.

You can use the following operation as many times as you like: select any integer 1 ≤ k ≤ n 1≤k≤n 1kn and do one of two things:

decrement by one k k k of the first elements of the array.
decrement by one k k k of the last elements of the array.
For example, if n = 5 n=5 n=5 and a = [ 3 , 2 , 2 , 1 , 4 ] a=[3,2,2,1,4] a=[3,2,2,1,4], then you can apply one of the following operations to it (not all possible options are listed below):

decrement from the first two elements of the array. After this operation a = [ 2 , 1 , 2 , 1 , 4 ] a=[2,1,2,1,4] a=[2,1,2,1,4];
decrement from the last three elements of the array. After this operation a = [ 3 , 2 , 1 , 0 , 3 ] a=[3,2,1,0,3] a=[3,2,1,0,3];
decrement from the first five elements of the array. After this operation a = [ 2 , 1 , 1 , 0 , 3 ] a=[2,1,1,0,3] a=[2,1,1,0,3];
Determine if it is possible to make all the elements of the array equal to zero by applying a certain number of operations.

Input
The first line contains one positive integer t ( 1 ≤ t ≤ 30000 ) t (1≤t≤30000) t(1t30000) — the number of test cases. Then t t t test cases follow.

Each test case begins with a line containing one integer n ( 1 ≤ n ≤ 30000 ) n (1≤n≤30000) n(1n30000) — the number of elements in the array.

The second line of each test case contains n n n integers a 1 … a n ( 1 ≤ a i ≤ 1 0 6 ) a_1…a_n (1≤a_i≤10^6) a1an(1ai106).

The sum of n n n over all test cases does not exceed 30000 30000 30000.

Output
For each test case, output on a separate line:

YES, if it is possible to make all elements of the array equal to zero by applying a certain number of operations.
NO, otherwise.
The letters in the words YES and NO can be outputed in any case.

input

4
3
1 2 1
5
11 7 9 6 8
5
1 3 1 3 1
4
5 2 1 10

output

YES
YES
NO
YES

题解

题意:给你一个序列,你可以执行一种操作:选择序列的前几位使之都减一;或者选择序列的后几位使之都减一。你可以执行任意次此操作,问是否可以使这个序列的每一个值都变为0。

一道很普通的模拟题,但是却卡了我一晚上。。。

首先可以想到,左边能消去的最大次数就是 a [ 0 ] a[0] a[0] 的值,从第2个数字一直到最后,能通过左边消去的值是越来越小的,与此同时,越来越大的部分被从右边消去。

维护两个值:

l l l a [ i ] a[i] a[i]从左边消去的部分。

r r r a [ i ] a[i] a[i]从右边消去的部分。

l l l 被初始化为a[0]。

从左到右枚举时应时刻保持 l + r = a [ i ] l+r=a[i] l+r=a[i],我们可以通过减少 l l l 和增大 r r r 来达到这种状态。如果无法保持,就代表任务无法完成。

#include <bits/stdc++.h>
#define _for(i, a) for(register int i = 0, lennn = (a); i < lennn; ++i)
#define _rep(i, a, b) for(register int i = (a), lennn = (b); i <= lennn; ++i)
using namespace std;
typedef long long LL;
const int maxn = 30005;

inline int read() {
    int x(0), f(1); char ch(getchar());
    while (ch<'0' || ch>'9') { if (ch == '-') f = -1; ch = getchar(); }
    while (ch >= '0'&&ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
    return x * f;
}

int n, a[maxn];

int sol() {
    _for(i, n) a[i] = read();
    LL l = a[0], r = 0;
    for(int i = 1; i < n; ++i) {
        if(r > a[i]) return 0;
        if(l + r < a[i]) r = a[i] - l;
        else l = a[i] - r;
    }
    return 1;
}

int main() {
    int T = read();
    _for(i, T) {
        n = read();
        printf("%s", sol() ? "YES\n":"NO\n");
    }
    return 0;
}

C2. Binary Table (Hard Version)(Codeforces Round #684 (Div. 2))

time limit per test:1 second
memory limit per test:256 megabytes
judge:CF

题意

给你一个 n × m n\times m n×m 的矩阵,每一个位置都只有 0 0 0 1 1 1 两种状态。

有一种操作:选择一个 2 × 2 2\times 2 2×2 的方块中的三个位置,使这三个位置的状态反转。你可以执行多次此操作。

如何能在 n × m n\times m n×m 步数内使矩阵全部变为 0 0 0

题解

码量很大的一道题。

枚举矩阵,但每次只考虑一个 2 × 2 2\times 2 2×2 的小矩阵,可以找到规律:除了右下角的小矩阵最多需要 4 4 4 步保证消去所有的1之外,其他的任意小矩阵都能保证在 2 2 2 步消去所有的1。

这个“消去”是指不影响当前小矩阵的上方、左方以及左上方的情况下(因为这些区域已经被消去所有的 1 1 1 了)消去当前矩阵的 1 1 1。至于影不影响右方、下方以及右下方则不必考虑,因为这些区域后面还会考虑枚举到。

接下来就是不断考虑各种转移方式,考验耐心。。

代码

#include <bits/stdc++.h>
#define _for(i, a) for(register int i = 0, lennn = (a); i < lennn; ++i)
#define _rep(i, a, b) for(register int i = (a), lennn = (b); i <= lennn; ++i)
#define nl(i, n) (i == n - 1 ? "\n":" ")
#define lu a[x][y]
#define ru a[x][y + 1]
#define ld a[x + 1][y]
#define rd a[x + 1][y + 1]
using namespace std;
typedef long long LL;
const int maxn = 105;

inline int read() {
    int x(0), f(1); char ch(getchar());
    while (ch<'0' || ch>'9') { if (ch == '-') f = -1; ch = getchar(); }
    while (ch >= '0'&&ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
    return x * f;
}

struct poi {
    int a[6];
    poi(int a0, int a1, int a2, int a3, int a4, int a5) {
        a[0] = a0;
        a[1] = a1;
        a[2] = a2;
        a[3] = a3;
        a[4] = a4;
        a[5] = a5;
    }
    void print() {
        _for(i, 6) printf("%d%s", a[i], nl(i, 6));
    }
};

int n, m;
int a[maxn][maxn];
vector<poi> pa;

void init() {
    pa.clear();
}

inline void doi(int x, int y, int op) {
    if(op == 1) {
        lu ^= 1;
        ru ^= 1;
        ld ^= 1;
        pa.push_back(poi(x, y, x, y + 1, x + 1, y));
    }
    else if(op == 2) {
        lu ^= 1;
        a[x][y - 1] ^= 1;
        ld ^= 1;
        pa.push_back(poi(x, y, x, y - 1, x + 1, y));
    }
    else if(op == 3) {
        lu ^= 1;
        a[x - 1][y] ^= 1;
        a[x][y - 1] ^= 1;
        pa.push_back(poi(x, y, x - 1, y, x, y - 1));
    }
    else {
        lu ^= 1;
        a[x - 1][y] ^= 1;
        ru ^= 1;
        pa.push_back(poi(x, y, x - 1, y, x, y + 1));
    }
}

void sol() {
    init();
    n = read(), m = read();
    _rep(i, 1, n) {
        _rep(j, 1, m) {
            scanf("%1d", &a[i][j]);
        }
    }
    for(int x = 1; x <= n; x += 2) {
        for(int y = 1; y <= m; y += 2) {
            if(x == n) --x;
            if(y == m) --y;
            if(lu && ru && ld && rd) {
                doi(x, y, 1);
                if(y + 1 < m) {
                    doi(x + 1, y + 2, 3);
                }
                else if(x + 1 < n) {
                    doi(x + 2, y + 1, 3);
                }
                else {
                    doi(x + 1, y + 1, 3);
                    doi(x + 1, y, 4);
                    doi(x, y + 1, 2);
                }
            }
            if(lu && ld && ru && !rd) {
                doi(x, y, 1);
            }
            if(lu && ld && rd && !ru) {
                doi(x + 1, y, 4);
            }
            if(!lu && ld && ru && rd) {
                doi(x + 1, y + 1, 3);
            }
            if(lu && ru && rd && !ld) {
                doi(x, y + 1, 2);
            }
            if(lu && ru && !ld && !rd) {
                doi(x + 1, y, 4);
                doi(x + 1, y + 1, 3);
            }
            if(lu && ld && !ru && !rd) {
                doi(x, y + 1, 2);
                doi(x + 1, y + 1, 3);
            }
            if(ld && rd && !lu && !ru) {
                if(x + 1 < n) doi(x + 1, y, 1);
                else {
                    doi(x, y, 1);
                    doi(x, y + 1, 2);
                }
            }
            if(ru && rd && !lu && !ld) {
                if(y + 1 < m) doi(x, y + 1, 1);
                else {
                    doi(x, y, 1);
                    doi(x + 1, y, 4);
                }
            }
            if(lu && rd && !ld && !ru) {
                doi(x, y, 1);
                doi(x + 1, y + 1, 3);
            }
            if(ld && ru && !lu && !rd) {
                doi(x + 1, y, 4);
                doi(x, y + 1, 2);
            }
            if(lu && !rd && !ru && !ld) {
                if(y + 1 < m) {
                    doi(x, y + 1, 2);
                    doi(x + 1, y + 1, 4);
                }
                else if(x + 1 < n) {
                    doi(x + 1, y, 4);
                    doi(x + 1, y + 1, 2);
                }
                else {
                    doi(x, y, 1);
                    doi(x, y + 1, 2);
                    doi(x + 1, y, 4);
                }
            }
            if(!lu && !rd && !ru && ld) {
                if(x + 1 < n) doi(x + 2, y, 4);
                else if(y + 1 < m) {
                    doi(x + 1, y + 1, 3);
                    doi(x+ 1, y + 1, 4);
                }
                else {
                    doi(x + 1, y, 4);
                    doi(x, y, 1);
                    doi(x + 1, y + 1, 3);
                }
            }
            if(!lu && rd && !ru && !ld) {
                if(y + 1 < m) {
                    doi(x + 1, y + 2, 3);
                }
                else if(x + 1 < n) {
                    doi(x + 2, y + 1, 3);
                }
                else {
                    doi(x + 1, y + 1, 3);
                    doi(x + 1, y, 4);
                    doi(x, y + 1, 2);
                }
            }
            if(!lu && !rd && ru && !ld) {
                if(y + 1 < m) {
                    doi(x, y + 2, 2);
                }
                else if(x + 1 < n) {
                    doi(x + 1, y + 1, 3);
                    doi(x + 1, y + 1, 2);
                }
                else {
                    doi(x, y, 1);
                    doi(x, y + 1, 2);
                    doi(x + 1, y + 1, 3);
                }
            }
        }
    }
    printf("%d\n", pa.size());
    _for(i, pa.size()) pa[i].print();
}

int main() {
    int T = read();
    _for(i, T) {
        sol();
    }
    return 0;
}

C. Engineer Artem(Codeforces Round #682 (Div. 2))

time limit per test:1 second
memory limit per test:256 megabytes
judge:CF

题意

给你一个 n × m n\times m n×m 的矩阵,你需要选择矩阵中的若干元素使之增加 1 1 1,使得改变后的矩阵的任意两个相邻的元素都不同。

题解

只需要使得每两个相邻位置的奇偶性不一样就行了。

代码

#include <bits/stdc++.h>
#define _for(i, a) for(register int i = 0, lennn = (a); i < lennn; ++i)
#define _rep(i, a, b) for(register int i = (a), lennn = (b); i <= lennn; ++i)
#define nl(i, n) (i == n - 1 ? "\n":" ")
using namespace std;
const int maxn = 105;

inline int read() {
    int x(0), f(1); char ch(getchar());
    while (ch<'0' || ch>'9') { if (ch == '-') f = -1; ch = getchar(); }
    while (ch >= '0'&&ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
    return x * f;
}

int a[maxn][maxn], n, m;

void sol() {
    _for(i, n) _for(j, m) a[i][j] = read();
    for(int i = 0, t = 1; i < n; ++i, t ^= 1) {
        for(int j = 0, tt = t; j < m; ++j, tt ^= 1) {
            printf("%d%s", ((a[i][j] & 1) == tt) ? a[i][j] : a[i][j] + 1, nl(j, m));
        }
    }
}

int main() {
    int T = read();
    _for(i, T) {
        n = read(), m = read();
        sol();
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值