版权声明:我这么弱的蒟蒻,虽然博文不是很好,但也请标明转发地址喵! https://blog.csdn.net/ACerAndAKer/article/details/82928001
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;
}