【Codeforces 1463D】Pair | 贪心、二分

题目链接:https://codeforces.com/contest/1463/problem/D

题目大意

给出一个序列,长度为n,现在支持有两种操作:
1:对于一组pair(x,y)选择pair中小的数留下
2:对于一组pair(x,y)选择pair中大的数留下
现在有1-2*n的数,数值分别为1-2*n,现在可以将这2*n个数进行任意的分组,对其中的x组执行1操作,n-x组执行2操作
输出有多少个x可以使得,执行完操作以后,得到给出的数组n

题目思路

挺卡的…
大概是自己菜了…
首先将题目给出的与未给出的分成两组
下面肯定两组之间进行匹配,那么贪心的去考虑:
1.给出的序列要成为最小值的x个,绝对是最小的x个,也就是前x个,并且这x个应该去匹配最大的未匹配的x个
2.同理,给出序列的[x+1,n]个应该去匹配未匹配的[1,n-x]个
这样就可以保证如果不可以匹配成功,那么一定不可以匹配成功

从这里也可以看出,这两者满足单调性.
所以这个应该是个区间问题.

所以只需要二分一下上边界、与下边界就可以了
至于为什么存在单调性,可以思考一下代码里的judge函数,或者上面的匹配规则.

Code:

/*** keep hungry and calm CoolGuang!  ***/
#pragma GCC optimize("Ofast","unroll-loops","omit-frame-pointer","inline")
#pragma GCC optimize(3)
#include <bits/stdc++.h>
#include<stdio.h>
#include<queue>
#include<algorithm>
#include<string.h>
#include<iostream>
#define debug(x) cout<<#x<<":"<<x<<endl;
#define d(x) printf("%lld\n",x);
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
const ll INF= 1e17;
const ll maxn = 4e5+700;
const int mod= 1e9+7;
const int up = 1e9;
template<typename T>inline void read(T &a){
    
    char c=getchar();T x=0,f=1;while(!isdigit(c)){
    
    if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){
    
    x=(x<<1)+(x<<3)+c-'0';c=getchar();}a=f*x;}
ll n,m,p;
ll num[maxn];
int vis[maxn],b[maxn];
int judge(int x){
    
    
    for(int i=1;i<=x;i++)
        if(num[i]>b[n-x+i]) return 1;///x大了
    for(int i=x+1;i<=n;i++)
        if(num[i]<b[i-x]) return 2;///x太小了
    return 0;
}
int main(){
    
    
    int T;scanf("%d",&T);
    while(T--){
    
    
        read(n);
        int cnt = 0;
        for(int i=1;i<=2*n;i++) vis[i] = 0;
        for(int i=1;i<=n;i++){
    
    
            read(num[i]);
            vis[num[i]] = 1;
        }
        for(int i=1;i<=2*n;i++){
    
    
            if(vis[i]) continue;
            b[++cnt] = i;
        }
        int l = 0,r = n,lbound = 0;
        while(l<=r){
    
    
            int mid = (l+r)/2;
            if(judge(mid) != 2){
    
    
                lbound = mid;
                r = mid - 1;
            }else l = mid+1;
        }
        l = 0,r = n;
        int ans = 0;
        while(l<=r){
    
    
            int mid = (l+r)/2;
            if(judge(mid) != 1){
    
    
                ans = max(ans,mid-lbound+1);
                l = mid + 1;
            }else r = mid-1;
        }
        printf("%d\n",ans);
    }
    return 0;
}

/***
10
0101011101
****/

猜你喜欢

转载自blog.csdn.net/qq_43857314/article/details/111596463