大家好,我是STL选手,我非常喜欢STL水题目
对于优先队列,也可以在$O(NlogN)$之内的时间之内解决这个问题
对于队列中的任意一个包含全部奶牛的区间$[L, R]$,设其中编号为$C_i$的奶牛存在$x$只,若$x \leq 2$那么如果除开排最左边的奶牛,会有两种结果:
1. **该奶牛在区间最左侧,更新左边界,可能得到的答案减小**
2. 区间大小不变
而且非常显然,**编号为$C_i$的奶牛若数量大于两只且存在某一只位于区间最左侧,则可以更新区间左侧,排除这只不必要的奶牛**
对于任意一个$R$,显然要更新答案我们则要取得最大的$L$,则可以通过统计区间内同种奶牛的数量来更新,在最后这个区间最左侧的奶牛显然在区间内没有其他任何一只同种奶牛
这个时候就可以使用优先队列来帮忙维护了,好写易懂,当$R$由$i-1$推进至$i$时,我们将$C_i$的统计数组加一,然后从优先队列中取出区间最左侧奶牛,若该奶牛符合退出队列的条件则将其退出队列,更新区间左边界,直到不能出队为止,计算左右距离...然后把$C_i$号奶牛入队,优先队列会自动帮我们维护它的信息在队列内的顺序...
那么很显然我们只要从头开始枚举,每枚举一个位置维护一下队列更新一下答案就完事儿了。特别的,若当前区间还未集齐所有奶牛则不更新答案(指开头的一部分)
当然本题非常easy,建议各种方法花式虐一遍,至于离散...可以百度一下.....
//2019/7/26->Riko->AtNCU->luoguP3029 #include<bits/stdc++.h> namespace Rikopack { bool digit (int ch) { return (ch <= '9' and ch >= '0');} inline int in () { int x = 0, ch = getchar(), base = 1; while (!digit(ch)) { if (ch == '-') base = -1; ch = getchar(); } while (digit(ch)) x = x*10+ch-'0', ch = getchar(); return x*base; } template <class T> inline void smin (T& x, T y) { if (x > y) x = y;} const int MAXINT = 2123456789, MININT = -2123456789; } using namespace std; using namespace Rikopack; const int N = 50500; struct node { int type, location; friend bool operator < (node x, node y) { return x.location > y.location; } } Cows[N]; int n, ans = MAXINT, kinds; int tmp[N], screened[N], numinheap[N], tag[N]; priority_queue <node> q; void work () { int cnt = 0; for (int i = 1; i <= n; ++i) { node x = Cows[i]; if (!screened[x.type]) ++cnt, screened[x.type] = true; numinheap[x.type]++; q.push(x); if (cnt >= kinds) { while (numinheap[q.top().type] > 1) { numinheap[q.top().type]--; q.pop(); } smin(ans, x.location-q.top().location); } } printf("%d", ans); } void prepare () { n = in(); for (int i = 1; i <= n; ++i) { Cows[i].location = in(); tmp[i] = Cows[i].type = in(); } sort(Cows+1, Cows+n+1); reverse(Cows+1, Cows+n+1); sort(tmp+1, tmp+n+1); int len = unique(tmp+1, tmp+n+1)-tmp-1; for (int i = 1; i <= n; ++i) { int& P = Cows[i].type; P = lower_bound(tmp+1, tmp+len+1, P)-tmp; if (!tag[P]) tag[P] = true, ++kinds; } work(); } int main () { prepare();}