hpuoj 1193: Interval
Interval [STL、双指针、二分]
题目链接 http://acm.hpu.edu.cn/problem.php?id=1193
或者
题目链接
http://acm.nyist.net/JudgeOnline/problem.php?pid=1316
看了题解有点迷,标程很厉害,很巧妙。先求出前缀和 presum[MAXN],区间长度至少是L,所以想到的是二分法,解决。二分具体:枚举左端点,从 N-L+1 到 l>=1;右端点一开始只有presum[N];所以左端点往左,维护一个右端点的前缀和,之后二分找 (左端点前缀和+M)>=presum [mid] ;
那么满足条件的就有 (有序数组个数 - mid) ; 维护有序需要将presum [r] 插入,我使用内存复制比较快;
#include <cstdio> #include <cstring> #include <cctype> #include <cmath> #include <set> #include <map> #include <list> #include <queue> #include <deque> #include <stack> #include <string> #include <vector> #include <iostream> #include <algorithm> #include <stdlib.h> #include <time.h> using namespace std; typedef long long LL; const int INF=2e9+1e8; const int MOD=1e9+7; const int MAXSIZE=1e6+5; const double eps=0.0000000001; void fre() { freopen("in.txt","r",stdin); freopen("out.txt","w",stdout); } #define memst(a,b) memset(a,b,sizeof(a)) #define fr(i,a,n) for(int i=a;i<n;i++) const int MAXN=10000+10; int presum[MAXN]; int bin[MAXN]; int temp[MAXN]; void insert(int pos,int value,int _size) { memcpy(temp,bin+pos,(_size-pos)*sizeof(int)); bin[pos]=value; memcpy(bin+pos+1,temp,(_size-pos)*sizeof(int)); } int main() { int t; scanf("%d", &t); while(t--) { int N, L, M; scanf("%d%d%d", &N, &L, &M); for(int i = 1; i <= N; i++) { int v; scanf("%d", &v); presum[i] = presum[i - 1] + v; } int T = N; int ans = 0; for(int l=N-L+1,len=0,r=N; l>=1; l--,r--) { int pos; pos=lower_bound(bin,bin+len, presum[r])-bin; insert(pos,presum[r],len++); pos=lower_bound(bin,bin+len,presum[l-1]+M)-bin; int temp=len-pos; ans+=temp; } printf("%d\n", ans); } return 0; } /**************************************************/ /** Copyright Notice **/ /** writer: wurong **/ /** school: nyist **/ /** blog : http://blog.csdn.net/wr_technology **/ /**************************************************/