Erasing Numbers Gym - 102452E(前缀和)

After a long statistics lecture, the students are about to leave the classroom when it suddenly starts to rain heavily. Since you don’t have your umbrella with you, you decide to stay in the classroom and hope the rain will end soon. Several minutes later, you are the only person still left in the classroom. You realize something interesting: there are N (N is odd) distinct integers written in a line on the blackboard. Because you are very bored, you decide to erase those numbers from the blackboard so that the janitor will have less work to do.

Piece of chalk and blackboard. Public domain.
Since you have just learned the concepts of median during the lecture, you invented the following erase-operation for three integers: wipe off the largest number and the smallest number from the blackboard, so that only the median of the three numbers remains. You decide to repeat the following process: choose three consecutive integers on the blackboard and apply erase-operation on them. After this operation, the number of integers on the blackboard will decrease by 2. Eventually, there will be only one integer left after this process is repeated N−12 times. Suddenly, you come up with an interesting question: which integers may survive until the end?

Input
The input contains multiple cases. The first line of the input contains a single integer T (1≤T≤1000), the number of cases.

For each case, the first line of the input contains a single integer N (1≤N≤5000, N is odd), the number of integers on the blackboard initially. The second line contains N distinct integers a1,a2,…,aN (1≤ai≤N), where ai (1≤i≤n) denotes the i-th integer on the blackboard.

It is guaranteed that the sum of N over all cases doesn’t exceed 104.

Output
For each case, print a string consisting of N characters in a single line. The i-th (1≤i≤N) character of the string should be ‘1’ if it is possible for ai to remain as the only integer in the end, otherwise it should be ‘0’.

Example
Input
2
5
3 1 2 5 4
3
2 3 1
Output
10001
100

牛客多校上有1e6的这道题,可以去学习一下:传送门

题意:
每次可以选连续3个数,删掉最大值最小值。最后序列剩下一个数。
求每个数是否能够剩下。

思路:
5000的数据范围可以想到 n 2 n^2 n2
那么遍历每个数X,之后将所有大于这个数的设置为1,小于这个数的设置为0。

那么保证0和1的数目相等,最后就能保证这个数剩下。因为0和1数目相等,那么每次一定可以找到一对相邻的0和1(或者0 X 1),删掉后使得0和1数目同时减1,最后减掉所有的0,1。

所以我们的问题就是能否通过操作使得0和1数目相等。0多就减少0,1多就减少1。


首先可以想到,如果3个数中有X,那么只能是 0 X 1或者1 X 0的形式,这样不能改变0和1数目相对大小。
所以对于X左边的数和右边的数分开考虑。

对于000和111,很明显可以减少掉2个0或者2个1,这样可以改变相对大小关系。但是除此,00100和11011等等序列也可以起到这样的作用。怎么知道哪些序列可以起到减少0或者减少1的作用呢?


答案是:
只要这个序列0的个数比1的个数大于等于3,那么就可以相对多减少2个0。

因为这个序列中0的个数比1的个数大于等于3,那么根据上述结论,每次寻找相邻的01或者10,就可以同时减少0的数目和1的数目,最后剩下的就是000。


所以枚举每个数以后得到0的数目和1的数目,0多就要减少0,那么就算前缀和,遇到0就加一,遇到1就减一,前缀和为负数就清0,大于等于3就减少2个0的数目。这样就做到了减少0的数目。对于1同理

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>

using namespace std;

typedef long long ll;

const int maxn = 5e3 + 7;
int vis[maxn],a[maxn];
int n;

bool check(int pos) {
    
    
    int zero = 0,one = 0;
    for(int i = 1;i <= n;i++) {
    
    
        if(a[i] == a[pos]) vis[i] = -1;
        else if(a[i] > a[pos]) {
    
    
            vis[i] = 1;
            one++;
        }
        else {
    
    
            vis[i] = 0;
            zero++;
        }
    }
    
    if(one == zero) return true;
    
    int ONE = one,ZERO = zero;
    int sum = 0;
    if(zero > one) {
    
    
        for(int i = 1;i <= pos - 1;i++) {
    
    
            if(zero == one) return true;
            if(vis[i] == 0) {
    
    
                sum++;
            } else if(vis[i] == 1) {
    
    
                sum--;
            }
            if(sum < 0) sum = 0;
            if(sum == 3) {
    
    
                zero -= 2;
                sum = 1;
            }
        }
        sum = 0;
        for(int i = pos + 1;i <= n;i++) {
    
    
            if(zero == one) return true;
            if(vis[i] == 0) {
    
    
                sum++;
            } else if(vis[i] == 1) {
    
    
                sum--;
            }
            if(sum < 0) sum = 0;
            if(sum == 3) {
    
    
                zero -= 2;
                sum = 1;
            }
        }
    } else {
    
    
        for(int i = 1;i <= pos - 1;i++) {
    
    
            if(zero == one) return true;
            if(vis[i] == 0) {
    
    
                sum--;
            } else if(vis[i] == 1) {
    
    
                sum++;
            }
            if(sum < 0) sum = 0;
            if(sum == 3) {
    
    
                one -= 2;
                sum = 1;
            }
        }
        sum = 0;
        for(int i = pos + 1;i <= n;i++) {
    
    
            if(zero == one) return true;
            if(vis[i] == 0) {
    
    
                sum--;
            } else if(vis[i] == 1) {
    
    
                sum++;
            }
            if(sum < 0) sum = 0;
            else if(sum == 3) {
    
    
                one -= 2;
                sum = 1;
            }
        }
    }
    return one == zero;
}

int main() {
    
    
    int T;scanf("%d",&T);
    int kase = T;
    int cnt = 0;
    while(T--) {
    
    
        scanf("%d",&n);
        cnt++;
        for(int i = 1;i <= n;i++) {
    
    
            scanf("%d",&a[i]);
        }

        for(int i = 1;i <= n;i++) {
    
    
            if(check(i)) {
    
    
                printf("1");
            } else {
    
    
                printf("0");
            }
        }
        printf("\n");
    }
    return 0;
}
//0111

猜你喜欢

转载自blog.csdn.net/tomjobs/article/details/108993931