http://acm.hdu.edu.cn/webcontest/contest_showproblem.php?pid=1001&ojid=0&cid=12578&hide=0
题意:t测试用例,n个数,给定的值k,求有几个连续的子区间,该区间max-min<k。
思路:双向队列。一个储存区间的最大值,一个储存区间的最小值,设立两个指针i,j,i一直往后走,当最大值-最小值>=k时,这是当前满足条件的最大区间,则其i-1-j+1个子区间都可以,当i走到数组的末尾时,j可能没有走到,这时j到i都可作为子区间。
感想:区间保存最大值,最小值,又在移动的一般都用到队列。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
int t,n,k,i,j,a[100005];
deque<int>high;
deque<int>low;
ll ans;
scanf("%d",&t);
while(t--)
{
high.clear();
low.clear();
ans=0;
scanf("%d%d",&n,&k);
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
for(j=i=1;i<=n;i++)//指针
{
while(!high.empty()&&high.back()<a[i])
high.pop_back();
high.push_back(a[i]);
while(!low.empty()&&low.back()>a[i])
low.pop_back();
low.push_back(a[i]);
while(!high.empty()&&!low.empty()&&(high.front()-low.front()>=k))//判断
{
ans+=i-j;
if(high.front()==a[j])
high.pop_front();
if(low.front()==a[j])
low.pop_front();
j++;
//cout<<j<<"!"<<endl;
//cout<<high.front()<<" "<<low.front()<<endl;
}
}
while(j<=n)//到数组尾部,j没到
{
ans+=i-j;
j++;
}
printf("%lld\n",ans);
///cout<<ans<<endl;
}
}