tag:单调队列
很惭愧,今天发现自己连滑动窗口都不会了,遂做了一些题
两滴水的高度之差大于等于D的情况下的最小花盆宽度
暴力思路:对于任意两点求水滴高度差是否大于等于D,若大于等于\(D\)则计算最下的两点距离 \(w\)
但这显然是能过但不完全过,手玩一下样例,是求\(\text{区间的最小长度}\),在\(\text{区间最大值和区间最小值的差}\) \(\geq D\)的情况下。
那么答案即为:
ans = min(ans, a[i].fi - a[l].fi);
发现和滑动窗口很像,但每次往区间加入元素,那如何区间弹出元素?
只要计算答案的时候每次左移\(\text{区间左端点}l\)即可,
// AC one more times
#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define endl '\n'
#define all(x) (x).begin(), (x).end()
#define inf64 0x3f3f3f3f3f3f3f3f
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<long long,long long> pll;
const int mod = 1e9 + 7;
const int N = 1e5 + 10;
int n, d;
int q1[N], q2[N];
// max min
int h1 = 1, t1 = 0, h2 = 1, t2 = 0;
pii a[N];
void solve()
{
cin>>n>>d;
for(int i = 1; i <= n; i++)
cin>>a[i].fi>>a[i].se;
sort(a + 1, a + n + 1);
int l = 1;
int ans = 1e9;
for(int i = 1; i <= n; i++)
{
while(h1 <= t1 && a[q1[t1]].se < a[i].se)
t1--;
q1[++t1] = i;
while(h2 <= t2 && a[q2[t2]].se > a[i].se)
t2--;
q2[++t2] = i;
while(l <= i && a[q1[h1]].se - a[q2[h2]].se >=d)
{
ans = min(ans, a[i].fi - a[l].fi);
l++;
while(h1 <= t1 && q1[h1] < l)
h1++;
while(h2 <= t2 && q2[h2] < l)
h2++;
}
}
if(ans == 1e9)
{
cout<<-1<<endl;
}
else
cout<<ans<<endl;
return;
}
int main()
{
std::ios::sync_with_stdio(false); cin.tie(nullptr), cout.tie(nullptr);
// 特殊输入 请注释上方,如__int128等
int TC = 1;
//cin >> TC;
for(int tc = 1; tc <= TC; tc++)
{
//cout << "Case #" << tc << ": ";
solve();
}
return 0;
}
标签:typedef,队列,Flowerpot,long,int,ans,USACO12MAR,fi,define
From: https://www.cnblogs.com/magicat/p/17316484.html