1. 程式人生 > >CodeForces - 958 F2 Lightsabers (medium) . (尺取法)

CodeForces - 958 F2 Lightsabers (medium) . (尺取法)

cloc const urn algorithm sync 序列 names lan 多少

傳送門

題意:給你一個n和m,再給你一個長為n的序列和一個長為m的序列,問最少要刪除多少元素,才能使第一個序列中的某個連續子串中恰好滿足第二個序列對數字的要求

題解:尺取法,設l為左界,r為右界,若c[a[r]]==b[a[r]]則說明對b中第a[r]個數字的個數要求達到滿足,則sum++。如果sum==m,則說明該子串滿足條件,那麽我們就要試圖將左界前進(為了使刪除要素更少,那麽r-l+1肯定是最小的),此處註意要記得c[a[l]]減一,如果它在減之前的個數等於b[a[l]]則說明刪減後,滿足條件的個數減1,即sum-1

#include <iostream>
#include 
<cstdio> #include <cmath> #include <algorithm> #include <map> #include <queue> #include <vector> #include <cstring> #include <iomanip> #include <set> #include<ctime> //CLOCKS_PER_SEC #define se second #define fi first #define ll long long #define
lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define Pii pair<int,int> #define Pli pair<ll,int> #define ull unsigned long long #define pb push_back #define fio ios::sync_with_stdio(false);cin.tie(0) const double Pi=3.14159265; const double e=2.71828182; const int N=3e5+5; const ull base
=163; const int INF=0x3f3f3f3f; using namespace std; int a[N]; int b[N];int main(){ int n,m; fio; cin>>n>>m; for(int i=1;i<=n;i++){ cin>>a[i]; } int sum=0; int pp=0; for(int i=1;i<=m;i++){ cin>>b[i]; if(b[i]==0) sum++; pp+=b[i]; } int c[N]; int l=1,r=1; int MIN=INF; int op=0; for(;;){ while(r<=n&&sum<m){ c[a[r]]++; if(c[a[r]]==b[a[r]])sum++; r++; } if(sum<m)break; MIN=min(MIN,r-l-pp); if(c[a[l]]==b[a[l]])sum--; c[a[l]]--; l++; } if(MIN!=INF) cout<<MIN<<endl; else cout<<-1<<endl; return 0; }

CodeForces - 958 F2 Lightsabers (medium) . (尺取法)