洛谷P3029 [USACO11NOV]牛的陣容Cow Lineup
阿新 • • 發佈:2018-12-13
STL大法好&&雙指標大法好
雙指標是一個玄學的東西
總的來說就是用一個變數l指在一個左端點,然後用一個變數r向右擴充套件直到符合要求的區間的條件為止,這玩意貌似也叫尺取法??
這道題資料範圍hin大怎麼辦?用map離散化一下就好了
具體實現
我們讀入的時候,用map記錄每個出現的種類,記錄總數cnt
然後我們需要按下標排個序,然後再開始圈答案
然後下面用雙指標,從l=1,r=1開始 向右擴充套件,r停止擴充套件的條件是l ~ r這個區間包含了cnt種牛,如何判斷呢?用個map,記錄每種牛出現的次數,沒出現過就map[id]++,tot++,當tot==cnt時,就可以更新l,讓l++,直到l ~ r這個區間包含的牛的種數小於cnt就好了,判斷l這個位置的map[id]==1,等於1說明就這一頭,所以tot–,然後必須要map[id]–,然後每次框到一個區間取min就好
程式碼
//By AcerMo
#include<map>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int M=50050;
int n,cnt;
int a[M],b[M],id[M],rk[M];
map<int,int>que;
map<int,bool>vis;
inline int read()
{
int x=0;char ch=getchar();
while (ch>'9'||ch<'0') ch=getchar();
while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x;
}
inline bool cmp(int x,int y){return a[x]<a[y];}
signed main()
{
n=read();
for (int i=1;i<=n;i++)
{
a[i]=read(),b[i]=read(),id[i]=i;
if (!vis[b[ i]]) vis[b[i]]=1,cnt++;
}
sort(id+1,id+n+1,cmp);
int l=1,r=1,tot=1,mi=2e9,f=0;
if (tot==cnt) f=1,mi=a[id[1]]-1;
que[b[id[1]]]++;
while (r<=n)
{
if (!f)
{
if (r==n) break;
r++;
if (!que[b[id[r]]]) tot++;
que[b[id[r]]]++;
if (tot==cnt) mi=min(mi,a[id[r]]-a[id[l]]),f=1;
}
else
{
if (que[b[id[l]]]==1) tot--,f=0;
que[b[id[l++]]]--;
if (f==1) mi=min(mi,a[id[r]]-a[id[l]]);
}
}
cout<<mi;
return 0;
}