尺取法 TwoPoint

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

3320

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

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

 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)推进,每次有最小值是更新答案区间信息就可以了

 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就可以了,统计可以相等的个数

 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)

 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

时间: 2024-10-03 21:53:37

尺取法 TwoPoint的相关文章

luogu 1712 区间(线段树+尺取法)

题意:给出n个区间,求选择一些区间,使得一个点被覆盖的次数超过m次,最小的花费.花费指的是选择的区间中最大长度减去最小长度. 坐标值这么大,n比较小,显然需要离散化,需要一个技巧,把区间转化为半开半闭区间,然后线段树的每一个节点表示一个半开半闭区间. 接着我们注意到需要求最小的花费,且这个花费只与选择的区间集合中的最大长度和最小长度有关. 这意味着如果最大长度和最小长度一定,我们显然是需要把中间长度的区间尽量的选择进去使答案不会变的更劣. 不妨把区间按长度排序,枚举每个最小长度区间,然后最大区间

poj 3320 Jessica&#39;s Reading Problem(尺取法+map/hash)

题目:http://poj.org/problem?id=3320 题意:给定N个元素的数组,找出最短的一段区间使得区间里面的元素种类等于整个数组的元素种类. 分析:暴力枚举区间的起点x,然后找到最小的y,使得区间[x,y]满足条件,x向有移位后变成x',现在的y'肯定不至于在y的左边.存状态的话map和hash都可以. map代码: #include <iostream> #include <set> #include <map> #include <cstdi

hihocoder-1483区间价值 (二分+尺取法)

题目链接: 区间价值 给定n个数A1...An,小Ho想了解AL..AR中有多少对元素值相同.小Ho把这个数目定义为区间[L,R]的价值,用v[L,R]表示. 例如1 1 1 2 2这五个数所组成的区间的价值为4. 现在小Ho想知道在所有的的v[L,R](1 <= L <= R <= n)中,第k小的值是多少. Input 第一行一个数T(T<=10),表示数据组数. 对于每一组数据: 第一行两个数n,k(1<=n<=200,000,1<=k<=n*(n+1

【转】毛虫算法&mdash;&mdash;尺取法

转自http://www.myexception.cn/program/1839999.html 妹子满分~~~~ 毛毛虫算法--尺取法 有这么一类问题,需要在给的一组数据中找到不大于某一个上限的"最优连续子序列" 于是就有了这样一种方法,找这个子序列的过程很像毛毛虫爬行方式,我管它叫毛毛虫算法,比较流行的叫法是"尺取法". 喏,就像图里的妹纸一样~ 还是举个栗子: Poj3061 给长度为n的数组和一个整数m,求总和不小于m的连续子序列的最小长度 输入 n = 1

51nod1127(尺取法)

题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1127 题意:中文题诶- 思路:尺取法 维护一个队列,若当前队首的元素在后面出现了,那么我们就将其删除,若当前队列里含有26个字母,我们就记录其size. 取所有size里面的最小值就是我们要的答案... 代码: 1 #include <iostream> 2 #include <stdio.h> 3 #include <string>

BestCoder Round #86 二,三题题解(尺取法)

第一题太水,跳过了. NanoApe Loves Sequence题目描述:退役狗 NanoApe 滚回去学文化课啦! 在数学课上,NanoApe 心痒痒又玩起了数列.他在纸上随便写了一个长度为 nnn 的数列,他又根据心情随便删了一个数,这样他得到了一个新的数列,然后他计算出了所有相邻两数的差的绝对值的最大值. 他当然知道这个最大值会随着他删了的数改变而改变,所以他想知道假如全部数被删除的概率是相等的话,差的绝对值的最大值的期望是多少. 输入描述 第一行为一个正整数 T,表示数据组数. 每组数

POJ 3320 尺取法,Hash,map标记

1.POJ 3320 2.链接:http://poj.org/problem?id=3320 3.总结:尺取法,Hash,map标记 看书复习,p页书,一页有一个知识点,连续看求最少多少页看完所有知识点 必须说,STL够屌.. #include<iostream> #include<cstring> #include<cmath> #include<queue> #include<algorithm> #include<cstdio>

HDU 5672 String 尺取法追赶法

String Problem Description There is a string S.S only contain lower case English character.(10≤length(S)≤1,000,000)How many substrings there are that contain at least k(1≤k≤26) distinct characters? Input There are multiple test cases. The first line

hdu-5672 String(尺取法)

题目链接: String Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) 问题描述 有一个 10\leq10≤长度\leq 1,000,000≤1,000,000 的字符串,仅由小写字母构成.求有多少个子串,包含有至少k(1 \leq k \leq 26)k(1≤k≤26)个不同的字母? 输入描述 输入包含多组数据. 第一行有一个整数T (1\leq T\leq 10)T(1≤T≤1