码迷,mamicode.com
首页 > 其他好文 > 详细

尺取法 TwoPoint

时间:2014-07-07 22:09:14      阅读:213      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   color   使用   os   

就是两个指针表示区间[l,r]的开始与结束然后根据题目来将端点移动,是一种十分有效的做法。适合连续区间的问题

3320

这道意思是一本书有n页,每一页上有一个知识点标号a[i]可能重复,要求选择一个最小的区间使得能够覆盖所有知识点

分析:[l,r]区间推进,统计区间中能够覆盖的知识点数,对于每一个l,r都是满足可以覆盖所有知识点的最小r,处理好区间知识点数的统计就好了

bubuko.com,布布扣
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <set>
 5 #include <algorithm>
 6 #include <map>
 7 #include <queue>
 8 #include<cmath>
 9 #include<vector>
10 #define maxn 1000010
11 #define maxm 100010
12 #define mod 1000000000000000000
13 #define INF 0x3f3f3f3f3f
14 using namespace std;
15 int n;
16 int a[maxn];
17 map<int,int>mp;
18 set<int>num;
19 int main (){
20     while(scanf("%d",&n)!=EOF){
21         num.clear();
22         mp.clear();
23         for(int i=0;i<n;++i){
24             scanf("%d",&a[i]);
25             num.insert(a[i]);
26         }
27         int l=0,r=0;
28         int m = num.size();
29         int cnt=0;
30         int ans=n;
31         while(l<n){
32             while(r<n&&cnt<m){
33                 if(mp[a[r]]==0){
34                     cnt++;
35                 }
36                 mp[a[r]]++;
37                 r++;
38             }
39             if(cnt<m)break;
40             ans =min(ans,r-l);
41             mp[a[l]]--;
42             if(mp[a[l]]==0){
43                 cnt--;
44             }
45             l++;
46         }
47         printf("%d\n",ans);
48     }
49 
50 }
poj3320

2566

给你一个数组(可为负数)m次询问,每次询问一个区间使得区间和的绝对值最接近给定的值,有多种随意输出一种

分析:预处理前缀和sum[i]这样可以O(1)查询区间和,然后sum数组从小到大排序(因为abs(sum[i]-sum[j])=abs(sum[j]-sum[i])所以顺序不影响答案,但可以方便尺取)然后就是O(n)推进,每次有最小值是更新答案区间信息就可以了

bubuko.com,布布扣
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <set>
 5 #include <algorithm>
 6 #include <map>
 7 #include <queue>
 8 #include<cmath>
 9 #include<vector>
10 #define maxn 1000010
11 #define maxm 100010
12 #define mod 1000000000000000000
13 #define INF 0x3f3f3f3f
14 using namespace std;
15 int n,m;
16 int a[maxn];
17 pair<int,int>p[maxn];
18 void query(int x){
19     int l=0,r=1,mmin=INF;
20     int ansl,ansr,ansx;
21     while(l<=n&&r<=n){
22         int y = p[r].first-p[l].first;
23         if(abs(y-x)<mmin){
24             mmin=abs(y-x);
25             ansx=y;
26             ansl = p[l].second;
27             ansr = p[r].second;
28         }
29         if(y>x)l++;
30         else if(y<x)r++;
31         else break;
32         if(l==r)r++;
33     }
34     if(ansl>ansr)swap(ansl,ansr);
35     printf("%d %d %d\n",ansx,ansl+1,ansr);
36 }
37 int main (){
38     while(scanf("%d%d",&n,&m)!=EOF){
39         if(n==0&&m==0)break;
40         p[0]=pair<int,int>(0,0);
41         int sum=0;
42         for(int i=1;i<=n;++i){
43             scanf("%d",&a[i]);
44             sum+=a[i];
45             p[i]=pair<int,int>(sum,i);
46         }
47         sort(p,p+n+1);
48         while(m--){
49             int x;
50             scanf("%d",&x);
51             query(x);
52         }
53     }
54 }
pos2566

2739

给你一个数,询问有多少个连续质数序列和等于该数例如53=5 + 7 + 11 + 13 + 17 

分析:筛法求质数,然后直接twopoint就可以了,统计可以相等的个数

bubuko.com,布布扣
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <set>
 5 #include <algorithm>
 6 #include <map>
 7 #include <queue>
 8 #include<cmath>
 9 #include<vector>
10 #define maxn 1000010
11 #define maxm 100010
12 #define mod 1000000000000000000
13 #define INF 0x3f3f3f3f
14 using namespace std;
15 int n,m;
16 int prime[maxn];
17 bool is_prime[maxn];
18 int  get_prime(int n){
19     int ans=0;
20     for(int i=2;i<=n;++i)is_prime[i]=true;
21     is_prime[0]=is_prime[1]=false;
22     for(int i=2;i<=n;++i){
23         if(is_prime[i]){
24             prime[ans++]=i;
25             for(int j=2*i;j<=n;j+=i)is_prime[j]=false;
26         }
27     }
28     return ans;
29 }
30 void query(int x){
31     int ans=0;
32     int l=0,r=0,sum=0;
33     while(1){
34         while(r<m&&sum<x){
35             sum+=prime[r++];
36         }
37         if(sum<x)break;
38         else if(sum==x)ans++;
39         sum-=prime[l++];
40     }
41     printf("%d\n",ans);
42 }
43 int main (){
44     m=get_prime(10010);
45     while(scanf("%d",&n)!=EOF){
46         if(n==0)break;
47         query(n);
48     }
49 }
poj2739

2100

给你一个数,询问有多少种连续自然数的平方和等于这个数,输出所有可能

分析:由上面的基础很简单了,对于每个数枚举区间,求和,推进区间,如果可以的话将区间记录最后输出就可以了,注意使用long long ,复杂度O(1e7)

bubuko.com,布布扣
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <set>
 5 #include <algorithm>
 6 #include <map>
 7 #include <queue>
 8 #include<cmath>
 9 #include<vector>
10 #define maxn 1000010
11 #define maxm 100010
12 #define mod 1000000000000000000
13 #define INF 0x3f3f3f3f
14 using namespace std;
15 vector<pair<long long ,long long > >ans;
16 void query(long long  x){
17     long long  l=1,r=1;
18     long long sum=0;
19     long long sq=0;
20     while(1){
21         while(sum<x){
22             sq=r*r;
23             sum+=sq;
24             r++;
25         }
26         if(sq>x)break;
27         if(sum==x){
28             ans.push_back(make_pair(l,r));
29         }
30         sum-=l*l;
31         l++;
32     }
33     long long m = ans.size();
34      printf("%lld\n",m);
35     for(long long  i=0;i<m;++i){
36         long long  ll = ans[i].first;
37         long long  rr = ans[i].second;
38         printf("%lld",rr-ll);
39         for(long long  j=ll;j<rr;++j){
40             printf(" %lld",j);
41         }
42          printf("\n");
43     }
44 }
45 int main (){
46     long long n;
47     while(scanf("%lld",&n)!=EOF){
48         if(n==0)break;
49         query(n);
50     }
51 }
poj2100

 

 

尺取法 TwoPoint,布布扣,bubuko.com

尺取法 TwoPoint

标签:style   blog   http   color   使用   os   

原文地址:http://www.cnblogs.com/shuzy/p/3812924.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!