就是两个指针表示区间[l,r]的开始与结束然后根据题目来将端点移动,是一种十分有效的做法。适合连续区间的问题
这道意思是一本书有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
给你一个数组(可为负数)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
给你一个数,询问有多少个连续质数序列和等于该数例如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
给你一个数,询问有多少种连续自然数的平方和等于这个数,输出所有可能
分析:由上面的基础很简单了,对于每个数枚举区间,求和,推进区间,如果可以的话将区间记录最后输出就可以了,注意使用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
时间: 2024-10-03 21:53:37