Subsequence HDU - 3530

原题链接

根据题意,很明显我们需要两个单调队列分别维护最小值与最大值.这里我用了双指针指向窗口的起点与终点.要注意的是如果差<m或者符合条件我们需要更新窗口的右端,如果>k我们需要更新窗口的左端

答案最小可以取0,所以maxn不要设置为负数

注意,第一次一定可以进while循环的,因为第一次队列差值为0,k最小=0

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int N = 100010;
 4 int ql[N],qh[N],a[N];
 5 int main()
 6 {
 7 //    freopen("in.txt","r",stdin);
 8     int m,k,n;
 9     while(scanf("%d%d%d",&n,&m,&k)!=EOF)//最大子区间最大最小值在mk之间 
10     {
11         long long maxn = 0;
12         int h1 = 0,t1 = -1,h2 = 0,t2 = -1;
13         fill(ql,ql+N,0); fill(qh,qh+N,0);
14         for(int i=1;i<=n;i++) scanf("%d",&a[i]);
15         for(int i=1,j = 0;i<=n;i++){//如果差<m更新j 如果>k,更新i 
16             while(h1<=t1&&ql[h1]<i) h1++;
17             while(h2<=t2&&qh[h2]<i) h2++;
18             while(j<=n&&(a[qh[h2]]-a[ql[h1]]<m||(a[qh[h2]]-a[ql[h1]]>=m&&a[qh[h2]]-a[ql[h1]]<=k))){
19                 j++;
20                 while(h1<=t1&&a[ql[t1]]>=a[j]) --t1;
21                 ql[++t1] = j;
22                 while(h2<=t2&&a[qh[t2]]<=a[j]) --t2;
23                 qh[++t2] = j;
24                 if(j<=n&&a[qh[h2]]-a[ql[h1]]>=m&&a[qh[h2]]-a[ql[h1]]<=k) maxn = max((long long)j-i+1,maxn);
25             }
26         }
27         printf("%lld\n",maxn);
28     }
29     return 0;
30 } 

 

上一篇:noip模拟74(待补)


下一篇:题解 Skip