http://acm.hdu.edu.cn/showproblem.php?pid=5288#include<stdio.h>解法1:rmq算法
#include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> #include<math.h> using namespace std; const int size=100010; int a[size]; int dMx[size][30]; int dMi[size][30]; void init_rmq(int n) { int i,j; for(i=1;i<=n;i++) dMx[i][0]=dMi[i][0]=a[i]; for(int j = 1; (1 << j) <= n + 1; j++) { for(int i = 0; i + (1 << j) - 1 < n + 1; i++) { dMx[i][j] = max(dMx[i][j - 1], dMx[i + (1 << (j - 1))][j - 1]); dMi[i][j] = min(dMi[i][j - 1], dMi[i + (1 << (j - 1))][j - 1]); } } } int get(int i,int j) { int index=int(log(double(j-i+1))/log(double(2))); int mx=max(dMx[i][index],dMx[j-(1<<index)+1][index]); int mn=min(dMi[i][index],dMi[j-(1<<index)+1][index]); return mx-mn; } int main() { int i,j,t,n,m,k,left,right,mid; long long sum=0; scanf("%d",&t); while(t--) { sum=0; scanf("%d%d",&n,&k); for(i=1;i<=n;i++) { scanf("%d",&a[i]); } init_rmq(n); for(i=1;i<=n;i++) { left=i;right=n; while(left<=right) { mid=(left+right)>>1; if(get(i,mid)<k) { left=mid+1; } else right=mid-1; } sum+=left-i; } printf("%I64d\n",sum); } } 解法2:单调队列
#include<stdio.h> #include<string.h> #include<iostream> #include<queue> using namespace std; const int size = 100010; deque<int > deq1,deq2; int a[size]; int main() { int i,j,k,n,m,t; long long ans; scanf("%d",&t); while(t--) { ans=0; scanf("%d%d",&n,&k); for(i=0;i<n;i++) { scanf("%d",&a[i]); } while(!deq1.empty()) deq1.pop_back(); while(!deq2.empty()) deq2.pop_back(); for(j=0,i=0;i<n;i++) { while(!deq1.empty()&&a[i]>deq1.back()) deq1.pop_back(); deq1.push_back(a[i]); while(!deq2.empty()&&a[i]<deq2.back()) deq2.pop_back(); deq2.push_back(a[i]); while(deq1.front()-deq2.front()>=k) { ans+=(i-j); if(deq1.front()==a[j]) deq1.pop_front(); if(deq2.front()==a[j]) deq2.pop_front(); j++; } } while(j<n) { ans+=(i-j); j++; } printf("%I64d\n",ans); } } 解法三: <pre style="font-family:Courier New;text-align:left;"><pre name="code" class="html">单调队列
#include<string.h>
#include<iostream>
#include<queue>
using namespace std;
const int size = 100010;
int deq1[size],deq2[size];
int a[size];
int main()
{
int i,j,k,n,m,t;
long long sum;
int l1,l2,r1,r2,l;
scanf("%d",&t);
while(t--)
{
l=0;
l1=l2=0;
r1=r2=-1;
sum=0;
scanf("%d%d",&n,&k);
for(i=0;i<n;i++)
scanf("%d",&a[i]);
for(i=0;i<n;i++)
{
while(l1<=r1&&a[i]<a[deq1[r1]]) r1--;
deq1[++r1]=i;
while(l2<=r2&&a[i]>a[deq2[r2]])
{
//printf("%d %d %d!",i,a[i],deq2[r2]);
r2--;
}
deq2[++r2]=i;
while(a[deq2[l2]]-a[deq1[l1]]>=k)
{
//printf("%d %d %d!\n",i,deq1[l1],deq2[l2]);
if(deq1[l1]<deq2[l2])
l=deq1[l1++]+1;
else
l=deq2[l2++]+1;
}
//printf("%d %d %d\n",i,deq1[l1],deq2[l2]);
//if((a[deq1[l1]]-a[deq2[l2]]<=k))
sum+=(i+1-l);
//printf("%d %d %d\n",i,i+1-l,l);
}
printf("%I64d\n",sum);
}
}
解法四:线段树(超时)
#include<stdio.h> #include<string.h> #include<iostream> #include<math.h> #include<time.h> #include<algorithm> using namespace std; int a[100010]; int mx[100010][30]; int rmq[100010][30]; int Max,Min; struct node { int l;int r; int mn;int mx; }tree[400010]; void init_tree(int left,int right,int pos) { int mid=(left+right)/2; if(left==right) { tree[pos].mn=tree[pos].mx=a[left]; return; } init_tree(left,mid,pos*2); init_tree(mid+1,right,pos*2+1); tree[pos].mx=max(tree[pos*2].mx,tree[pos*2+1].mx); tree[pos].mn=min(tree[pos*2].mn,tree[pos*2+1].mn); } void get(int le,int ri,int left,int right,int pos) { if(le==left&&ri==right) { Max=max(tree[pos].mx,Max); Min=min(Min,tree[pos].mn); return ; //return tree[pos].mx-tree[pos].mn; } int mid=(left+right)/2; if(ri<=mid) get(le,ri,left,mid,pos*2); else if(le>mid) get(le,ri,mid+1,right,pos*2+1); else { get(le,mid,left,mid,pos*2); get(mid+1,ri,mid+1,right,pos*2+1); } } /*void init_rmq(int n) { int i,j; for(i=0;i<n;i++) rmq[i][0][1]=rmq[i][0][0]=a[i]; // for(i=n-1;i>=0;i--) // { // for(j=1;i+(1<<(j-1))<n;j++) // //for(j=1;j<=25;j++) // { // rmq[i][j][0]=min(rmq[i][j-1][0] ,rmq[i+(1<<(j-1))][j-1][0]); // rmq[i][j][1]=max(rmq[i][j-1][11] ,rmq[i+(1<<(j-1))][j-1][1]); // } // } for(j=1;(1<<j)<=n;j++) { for(i=0;i+(1<<j)-1<n&&i+(1<<(j-1))<n;i++) { rmq[i][j][0]=min(rmq[i][j-1][0],rmq[i+(1<<(j-1))][j-1][0]); rmq[i][j][1]=max(rmq[i][j-1][1],rmq[i+(1<<(j-1))][j-1][1]); } } }*/ /*int ask(int l,int r,int fg) { int exp=(int)(log(double(r-l+1))/log(2.0)); if(fg==1) return max(rmq[l][exp][1],rmq[r-(1<<(exp))+1][exp][1]); else return min(rmq[l][exp][0],rmq[r-(1<<(exp))+1][exp][0]); }*/ int main() { //int start = clock(); int i,j,mid,k,m,t,ans,left,right,n; long long sum; scanf("%d",&t); while(t--) { sum=0; scanf("%d%d",&n,&k); for(i=0;i<n;i++) scanf("%d",&a[i]); init_tree(0,n-1,1); // init_rmq(n); // for(i=0;i<n;i++) // { // for(j=i;j<n;j++) // printf("%d %d ,",ask(i,j,0),ask(i,j,1)); // printf("\n"); // } // printf("%d %d %d\n",ask(0,3,1)-ask(0,3,0),ask(0,3,1),ask(0,3,0)); // printf("%d %d %d\n",ask(1,3,1)-ask(1,3,0),ask(1,3,1),ask(1,3,0)); // printf("%d %d %d\n",ask(2,3,1)-ask(2,3,0),ask(2,3,1),ask(2,3,0)); for(i=0;i<n;i++) { left=i;right=n-1; while(left<=right) { mid=(left+right)/2; //if(ask(i,mid,1)-ask(i,mid,0)<k) Max=-1; Min=2147483640; get(i,mid,0,n-1,1); if(Max-Min<k) { // ans=mid; // left=mid+1; left=mid+1; } else right=mid-1; } sum+=left-i; //sum+=ans-i; } printf("%I64d\n",sum); } //int end = clock(); //printf("%d ms\n", end - start); } 还有跟高级的解法
http://www.cnblogs.com/names-yc/p/4665651.html 树状数组
http://www.cnblogs.com/andyqsmart/p/4665423.html (线段树)