[题解]CF1824A LuoTianyi and the Show

思路

首先,我们需要确定每一种方案的第一个人,那么,可以分为三种情况(其中 \(a\)\(x_i = -1\) 的数量,\(b\)\(x_i = -2\) 的数量,\(len\) 为原序列 \(x\) 中权值大于 \(0\) 的序列排序并离散化的数量):

  1. 选择 \(x_i = -1\) 的人开始。那么,会在 \(m\) 点坐下,那么,对于所有 \(x_i = -2\) 的人都没有位置坐。想象一下他们坐下的顺序,如果当前 \(x_i = -1\),并且有一个 \(x_j = m - i\)(即当前需要选择的位置),那么,显然优先选择 \(j\) 坐。所以,此贡献为 \(\min(m,a + len)\)
  2. 选择 \(x_i = -2\) 的人开始,同理,贡献为 \(\min(m,b + len)\)
  3. 选择 \(x_i > 0\) 的人开始,那么,能够在 \(x_i\) 左边坐下的人,要么 \(x_j < x_i\) 要么是 \(-1\);右边同理。所以,对于左边的答案 \(A\)\(\min(a + i,a_i - 1)\),右边的答案 \(B\) 同理 \(b + len - i - 1\)。该位置的贡献是 \(A + 1 + B\)

在这里,我们排序并且离散化的意义是,使第 \(3\) 中情况中,快速得出 \(x_j < x_i\)\(x_k > x_i\) 的数量。

Code

#include <bits/stdc++.h>  
#define re register  
  
using namespace std;  
  
const int N = 1e5 + 10;  
int T,n,m;  
  
inline int read(){  
    int r = 0,w = 1;  
    char c = getchar();  
    while (c < '0' || c > '9'){  
        if (c == '-') w = -1;  
        c = getchar();  
    }  
    while (c >= '0' && c <= '9'){  
        r = (r << 3) + (r << 1) + (c ^ 48);  
        c = getchar();  
    }  
    return r * w;  
}  
  
int main(){  
    T = read();  
    while (T--){  
        int a = 0,b = 0,ans = 0;  
        vector<int> t,arr;  
        n = read();  
        m = read();  
        for (re int i = 1;i <= n;i++){  
            int x;  
            x = read();  
            if (x == -1) a++;  
            else if (x == -2) b++;  
            else t.push_back(x);  
        }  
        int len = t.size();  
        sort(t.begin(),t.end());  
        for (re int i = 0;i < len;i++){  
            if (!i) arr.push_back(t[i]);  
            else if (t[i] != t[i - 1]) arr.push_back(t[i]);  
        }//排序 + 离散化   
        len = arr.size();  
        for (int i = 0;i < len;i++){  
            int A = 0,B = 0;  
            if (a + i <= arr[i] - 1) A = a + i;  
            else A = arr[i] - 1;  
            if (b + len - i - 1 <= m - arr[i]) B = b + len - i - 1;  
            else B = m - arr[i];  
            ans = max(ans,A + 1 + B);  
        }  
        printf("%d\n",max({ans,min(m,a + len),min(m,b + len)}));//3 种情况取最大值   
    }  
    return 0;  
}  
posted @ 2024-06-25 12:27  WBIKPS  阅读(9)  评论(0)    收藏  举报