标签:
题意:给你一个序列,求有多少区间 满足 区间最大值,最小值的差小于K
思路: ST处理最大最小, 枚举起点,二分终点,计算值
(先贴个标程,自己写的无限WA…)
#include<cstdio> #include<cstring> #include<cmath> #define LL __int64 #define Min(a,b) ((a)<(b)?(a):(b)) #define Max(a,b) ((a)>(b)?(a):(b)) const int N = 200007; int min[N][20]; int max[N][20]; int queryMin(int l,int r){ int k=log2((double)(r-l+1)); return Min(min[l][k],min[r-(1<<k)+1][k]); } int queryMax(int l,int r){ int k=log2((double)(r-l+1)); return Max(max[l][k],max[r-(1<<k)+1][k]); } int calc(int l,int r){ int k=log2((double)(r-l+1)); int MAX=Max(max[l][k],max[r-(1<<k)+1][k]); int MIN=Min(min[l][k],min[r-(1<<k)+1][k]); return MAX-MIN; } char filein[]={"9.in"}; char fileot[]={"9.out"}; int main(){ // for(int t=0;t<10;++t){ // filein[0]=t+‘0‘; // fileot[0]=t+‘0‘; // freopen(filein,"r",stdin); // freopen(fileot,"w",stdout); int T; int n,k,i,j,p; LL ans; scanf("%d",&T); while(T--){ scanf("%d%d",&n,&k); for(i=1;i<=n;++i){ scanf("%d",&j); min[i][0]=max[i][0]=j; } for(j=1;(1<<j)<=n;++j) for(i=1;i+(1<<j)-1<=n;++i){ p=(1<<(j-1)); min[i][j]=Min(min[i][j-1],min[i+p][j-1]); max[i][j]=Max(max[i][j-1],max[i+p][j-1]); } int l,r; ans=0; for(i=1;i<=n;++i){ l=i,r=n; while(l+1<r){ p=(l+r)>>1; if(calc(i,p)<k){ l=p; } else{ r=p; } } if(calc(i,r)<k){ p=r; ans=ans+(LL)(r-i+1); } else{ p=l; ans=ans+(LL)(l-i+1); } } printf("%I64d\n",ans); } // fclose(stdin); // fclose(stdout); // } return 0; }
(自己 WA)
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<vector> using namespace std; int dmax[100001][30]; int dmin[100001][30]; vector<int> Line; void RMQ_max(const vector<int>& A) { int n = A.size(); for(int i = 0; i < n; ++i) dmax[i][0] = A[i]; for(int j = 1; (1<<j) <= n; ++j) for(int i = 0; i + (1<<j) - 1 < n; ++i) dmax[i][j] = max(dmax[i][j-1],dmax[i+(1<<(j-1))][j-1]); } int RMQmax(int L,int R) { int k = 0; while((1<<(k+1)) <= (R-L+1)) k++; return max(dmax[L][k],dmax[R-(1<<k)+1][k]); } //Min void RMQ_min(const vector<int>& A) { int n = A.size(); for(int i = 0; i < n; ++i) dmin[i][0] = A[i]; for(int j = 1; (1<<j) <= n; ++j) for(int i = 0; i + (1<<j) - 1 < n; ++i) dmin[i][j] = min(dmin[i][j-1],dmin[i+(1<<(j-1))][j-1]); } int RMQmin(int L,int R) { int k = 0; while((1<<(k+1)) <= (R-L+1)) k++; return min(dmin[L][k],dmin[R-(1<<k)+1][k]); } int main() { int t,n,num,k; scanf("%d",&t); while(t--) { Line.clear(); scanf("%d %d",&n,&k); for(int i = 0; i <n; ++i) { scanf("%d",&num); Line.push_back(num); } int L,R; RMQ_max(Line); RMQ_min(Line); __int64 ans = 0; for(int i = 0; i < n; ++i) { int l = i, r = n-1; while(l + 1< r) { int m = (l + r + 1) >> 1; int Min = RMQmin(l,m); int Max = RMQmax(l,m); if(Max - Min < k) l = m; else r = m; } if(RMQmax(i,r) - RMQmin(i,r) < k) ans +=(__int64) (r-i+1); else ans +=(__int64) (l-i+1); } printf("%I64d\n",ans); } }
标签:
原文地址:http://www.cnblogs.com/aoxuets/p/4700423.html