尺取法。。

来源:互联网 发布:java swing教程 pdf 编辑:程序博客网 时间:2024/04/29 04:05

尺取法:反复推进区间的开头和末尾,来求满足条件的最小区间的方法被称为尺取法。

一般区间有连续或者单调等特点。

例题:

poj 2566

求任意子序列和的绝对值与所给值相差最小的区间

求出前N项的和构成新数组,从小到大排序,再用尺取法做。。。

这题恶心,,,不想多说

#include<cstdio>#include<algorithm>#include<iostream>using namespace std;typedef pair<int,int> P;const int maxn = 1e5+10;const int inf = 0x3f3f3f;int n,m,k;P p[maxn];int get_sum(int &l,int &r,int &from,int &to,int &result,int k) {if(l>=r) return INT_MIN;int sum = p[r].first - p[l].first;if(abs(sum-k)<abs(result-k)) {from = min(p[l].second,p[r].second);to = max(p[l].second,p[r].second);result = sum;}return sum;}int main() {while(~scanf("%d%d",&n,&m)) {if(!n&&!m) return 0;p[0] = make_pair(0,0);for(int i=1; i<=n; i++) {scanf("%d",&p[i].first);p[i].first+=p[i-1].first;p[i].second = i;}sort(p,p+n+1);while(m--) {scanf("%d",&k);int result = 0x80808080;int sum = 0x80808080;int from;int to;int l=0,r=0;for(;;) {while(r<n&&sum<k) {sum = get_sum(l,++r,from,to,result,k);}if(sum<k) break;//子序列和的绝对值最大值比k小sum = get_sum(++l,r,from,to,result,k);}printf("%d %d %d\n",result,from+1,to);}}}

谁能告诉我0x80808080,INT_MN,0x3f3f3f到底是些什么东西!!。。


poj 2739

题意:给定一个数n,求任意连续素数序列之和与n相等的序列总数。

如 53 has two representations 5 + 7 + 11 + 13 + 17 and 53(素数序列必须连续)

先素数打个表。。。

#include<cstdio>#include<algorithm>using namespace std;const int maxn = 1e4+10;int prime[maxn];bool is_prime[maxn];int p = 0;void sieve(){for(int i=0;i<=maxn;i++) is_prime[i] = true;is_prime[0] = is_prime[1] = false;for(int i=2;i<=maxn;i++){if(is_prime[i]){prime[p++] = i;for(int j=2*i;j<=maxn;j+=i) is_prime[j] = false;}}}int main(){int n;sieve();while(~scanf("%d",&n)){if(!n) return 0;int res = 0;int s = 0,t = 0,sum = 0;for(;;){if(sum==n) res++;while(t<p&&sum<n){sum+=prime[t++];if(sum==n) res++;}if(sum<n) break;sum-=prime[s++];}printf("%d\n",res);}}


poj 2100

题意:给定一个数n(挺大的),求任意连续整数序列的平方的和等于n的这些序列。

如:

input   2030

output  

2(表示有两个序列可以等于2030)4 21 22 23 24(第一个数为该序列的整数个数,后面为每个整数)3 25 26 27
21^2+22^2+23^2+24^2 = 2030

题目的输出很烦,看了网上的,用到了vector。。还是不知道使用这些数据结构啊。。。

#include<cstdio>#include<algorithm>#include<cmath>#include<vector>using namespace std;typedef  long long ll;const int maxn = 1e6;vector<pair<ll,ll> > ans;int main() {ll n;while(~scanf("%lld",&n)){ll s = 1;ll t = 1;ll sum = 0;while(s*s<=n){while(t*t<=n&&sum<n){sum+=t*t;t++;}if(sum==n){ans.push_back(make_pair(s,t));//printf("%lld %lld\n",s,t);}sum-=s*s;s++;}ll num = ans.size();printf("%lld\n",num);for(int i=0;i<num;i++){printf("%lld",ans[i].second-ans[i].first);for(int j=ans[i].first;j<ans[i].second;j++){printf(" %lld",j);}printf("\n");}}}

总结:尺取法总的来说比较容易,只要知道了题目要用到尺取法,应该就可以做出来了,剩下的就是细节实现问题。

三个题目,大致框架都是一样。


0 0