题意:
求满足区间中>=m的数>=k个的区间有多少
思路:
记小于m的数为0,大于等于m的为1,用sum维护区间和
然后我的做法是枚举右端点,二分左端点得到答案,复杂度O(nlogn)
/* *********************************************** Author :devil ************************************************ */ #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <vector> #include <queue> #include <set> #include <map> #include <string> #include <cmath> #include <stdlib.h> using namespace std; typedef long long LL; const int inf=0x3f3f3f3f; const int mod=1e9+7; const int N=2e5+10; int sum[N],k; int fun(int p) { int l=1,r=p; while(l<=r) { int mid=(l+r)>>1; if(sum[p]-sum[mid]>=k) l=mid+1; else r=mid-1; } return r+1; } int main() { //freopen("in.txt","r",stdin); int t,n,m,x; scanf("%d",&t); while(t--) { scanf("%d%d%d",&n,&m,&k); memset(sum,0,sizeof(sum)); for(int i=1;i<=n;i++) { scanf("%d",&x); sum[i]=sum[i-1]+(x>=m?1:0); } LL ans=0; int r; for(r=1;r<=n;r++) if(sum[r]>=k) break; for(int i=r;i<=n;i++) ans+=fun(i); printf("%I64d ",ans); } return 0; }
然后标解是two-pointer,处理完后枚举左端点,然后指针标记右端点
当区间内个数<k时就r++,大于n就跳出了,时间复杂度O(n)
这个题没有卡nlogn真是良心。。。
/* *********************************************** Author :devil ************************************************ */ #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <vector> #include <queue> #include <set> #include <map> #include <string> #include <cmath> #include <stdlib.h> using namespace std; typedef long long LL; const int inf=0x3f3f3f3f; const int mod=1e9+7; const int N=2e5+10; int sum[N]; int main() { //freopen("in.txt","r",stdin); int t,n,m,k,x; scanf("%d",&t); while(t--) { scanf("%d%d%d",&n,&m,&k); for(int i=1;i<=n;i++) { scanf("%d",&x); sum[i]=sum[i-1]+(x>=m?1:0); } LL ans=0; int r=1; for(int l=1;l<=n;l++) { while(r<=n&&sum[r]-sum[l-1]<k) r++; if(r>n) break; ans+=(n-r+1); } printf("%I64d ",ans); } return 0; }