题解:P4792 [BalticOI 2018] 火星人的 DNA

· · 题解

前言

赛场上把双指针拆成了 r 个???然后就没过。赛后一想就通五分钟过了,所以写个题解纪念下我的 shaber 时刻。

思路

对于一个左端点为 l 的区间,若右端点 r 符合所有条件,那么所有比 r 大的右端点都可以,且 l 单调递增时, r 也是单调递增的,所以想到了双指针。

#include<iostream>
#include<algorithm>
#include<cmath>
#include<iomanip>
#include<cstdio>
#include<string>
#include<deque>
#include<stack>
#include<queue>
#include<vector>
#include<stdio.h>
#include<map>
#include<set>
#include<string.h>
#include<time.h>
#include<stdlib.h>
#include<bitset>
using namespace std;
const int N=2e5+5;
int n,k,g;
int a[N];
int cnt[N],minn[N],b[N],q[N];
int main(){
    cin>>n>>k>>g;
    for(int i=1;i<=n;i++)cin>>a[i];
    for(int i=1;i<=g;i++){
        cin>>b[i]>>q[i];
        minn[b[i]]=q[i];
    }
    int les=g,r=0;
    int ans=99824435;
    for(int i=1;i<=n;i++){
        if(i!=1){
            cnt[a[i-1]]--;
            if(cnt[a[i-1]]<minn[a[i-1]])les++;
        }
        while(r<=n&&les){
            r++;
            cnt[a[r]]++;
            if(cnt[a[r]]==minn[a[r]]){
                les--;
            }
        }
        if(r<=n){
            ans=min(ans,r-i+1); 
        }
    }
    if(ans==99824435)puts("impossible");
    else cout<<ans;
    return 0;
}