• 【尺取法】POJ3061&&POJ3320


    SubsequencePOJ3061

    题意:

    求出总和不小于S的连续子序列的长度的最小值。

    思路:

    二分查找的话,前缀和是满足单调性的,计算从每一个数开始总和刚好大于s的长度。

    具体实现就是:二分搜索s[i]+s是否存在于前缀和数组中,就是查找以i+1开头的总和刚好大于s的最短长度。

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    using namespace std;
    const int maxn=1e5+5;
    int sum[maxn];
    int main()
    {
        int t;
        cin>>t;
        while(t--)
        {
            int n,S;
            cin>>n>>S;
            for(int i=0;i<n;i++)
            {
                int x;
                cin>>x;
                sum[i+1]=sum[i]+x;
            }
            if(sum[n]<S)
            {
                puts("0");
                continue;
            }
            int res=n;
            for(int s=0;sum[s]+S<=sum[n];s++)
            {
                int t=lower_bound(sum+s,sum+n,sum[s]+S)-sum;
                res=min(res,t-s);
            }
            cout<<res<<endl;
        }
        return 0;
    }

    尺取法:

    常用的解题技巧:尺取法

    Jessica's Reading ProblemPOJ3320

    题意:看最小的页数,获得整本书的所有知识点。求这个页数是多少。(页数必须连续)

    思路:所有知识点都被覆盖==每个知识点出现的次数都不小于1

       可以利用二叉树等数据结构来存储[s,t]区间上每个知识点的出现次数。

       从区间的最开头把s去除之后,s上书写的知识点的出现次数就要减一,如果此时这个知识点的出现次数为0,在同一个知识点再次出现前,不停将区间末尾t向后推进。

       时间:O(PlogP)

       ①用利用set集合里面元素的唯一性,将a[i]的所有元素放到里面去,这样就知道了一共有几个知识点。

       ②尺取法的原理是从起始left到末端right中寻找答案,然后利用map的映射,获得每个知识点所出现的数目即可。

       ③退出条件是sun < 知识点数目。

    #include
    #include
    #include
    #include
    #include
    using namespace std;
    
    int p;
    int a[1000000 + 10];
    
    void solve(){
        set  ind;
        for (int i = 0; i < p; i++){
            ind.insert(a[i]);
        }
        int left = 0, right = 0, sum = 0;
        map  ans;
        int res = p;//假设全部都看一遍
        while (true){
            while (right < p && sum < ind.size()){
                //printf("ans[] = %d
    ", ans[a[right]]);
                if (ans[a[right++]]++ == 0){
                    sum++;
                }
            }
            //printf("sum = %d
    ", sum);
            if (sum < ind.size()) break;
            res = min(res, right - left);
            if (--ans[a[left++]] == 0){//注意,这里不论if条件是否成立,--ans[a[left++]]的加减都会执行
                sum--;
            }
        } 
        printf("%d
    ", res);
    }
    
    int main(){
        while(scanf("%d", &p) != EOF){
            memset(a, 0, sizeof(a));
            for (int i = 0; i < p; i++){
                scanf("%d", a + i);
            }
            solve();
        }
        return 0;
    }
  • 相关阅读:
    kickstart-G
    some advice in work
    Java Applet:练习TextField类和TextArea类的文本事件
    jquery带下拉菜单和焦点图
    炫酷的CSS3抖动样式:CSS Shake
    CSS: iPhone Custom CSS
    css sprite技巧详解
    CSS缎带效果
    css 采集下载
    CSS控制表格嵌套
  • 原文地址:https://www.cnblogs.com/Kohinur/p/9037727.html
Copyright © 2020-2023  润新知