• 尺取法 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
    ",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
    ",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
    ",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
    ",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("
    ");
    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
  • 相关阅读:
    Python实现支持并发、断点续传的FTP
    Python IDE PyCharm的基本快捷键和配置简介
    SQL查询一个月第一天/最后一天及日期格式化
    MySQL 获得当前日期时间(以及时间的转换)
    逻辑学合取,析取,蕴含,双蕴含
    数据结构是一种用于实现集合的基本编程结构
    HttpClient的包含注意事项
    Jinja2 简明使用手册
    CGI编程学习
    python and、or以及and-or
  • 原文地址:https://www.cnblogs.com/shuzy/p/3812924.html
Copyright © 2020-2023  润新知