1. 程式人生 > >洛谷P3029 [USACO11NOV]牛的陣容Cow Lineup

洛谷P3029 [USACO11NOV]牛的陣容Cow Lineup

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; }