【Codeforces1463D】ペア|貪欲、2点

件名リンク:https//codeforces.com/contest/1463/problem/D

トピック

長さがnのシーケンスが与えられると、2つの操作がサポートされるようになりました:
1:对于一组pair(x,y)选择pair中小的数留下
2:对于一组pair(x,y)选择pair中大的数留下
1〜2 * nの数値があり、値はそれぞれ1〜2 * nです。これらの2 * nの数値は、任意にグループ化できます。 xグループは1回の操作を実行し、nxグループは2回の操作を実行し
ます。出力できるxの数は?操作が完了すると、指定された配列nが取得されます。

トピックのアイデア

それはかなり厄介です...
おそらくそれはあなた自身の食べ物です...
最初に、与えられた質問と与えられていない質問を2つのグループに分けます
。2つのグループは一致する必要があるので、貪欲に検討してください
。1。与えられたシーケンスが最小のxになるはずです、絶対に最小のx、つまり最初のx、およびこれらのxは最大の不一致x
2と一致する必要があります。同様に、指定されたシーケンスの[x + 1、n]は[1、nx]不一致と一致する必要があります。
一致が成功しない場合、一致が成功してはならないことが保証されるように

このことから、2つが単調性を満たしていることもわかります。
したがって、これは区間の問題であるはずです。

したがって、上限と下限を2つに分割するだけで済みます。
単調性がある理由については、コード内のジャッジ関数または上記のマッチングルールについて考えることができます。

コード:

/*** 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