• HDU6231(二分+尺取)


    Alice are given an array A[1..N] with N numbers.
    
    Now Alice want to build an array B by a parameter K as following rules:
    
    Initially, the array B is empty. Consider each interval in array A. If the length of this interval is less than K, then ignore this interval. Otherwise, find the K-th largest number in this interval and add this number into array B.
    
    In fact Alice doesn't care each element in the array B. She only wants to know the M-th largest element in the array B. Please help her to find this number.
     
    
    Input
    The first line is the number of test cases.
    
    For each test case, the first line contains three positive numbers N(1≤N≤105),K(1≤K≤N),M. The second line contains N numbers Ai(1≤Ai≤109).
    
    It's guaranteed that M is not greater than the length of the array B.
     
    
    Output
    For each test case, output a single line containing the M-th largest element in the array B.
     
    
    Sample Input
    2
    5 3 2
    2 3 1 5 4
    3 3 1
    5 8 2
     
    
    Sample Output
    3
    2

    正确:

    反向思维:

           首先所求答案一定为A数组中的元素,通过二分寻找元素X ;

           然后通过  尺取法以O(n)的时间复杂度 找到   所有A的连续子区间    中   第K大元素>=X的区间  

               因为l,r遍历,如果[l,r]中第K大元素>=X, 后续加入的元素没有影响  ans(所求区间数 )+= n-r

          所以X在所有第K大元素组成的区间中至少为ans大(因为[l,r]后序加入的元素中可能有比X大的元素,也有等于X的元素)

          通过叫ans与m的大小,最后求得答案 

    注意:X不一定在所有第K大组成的元素中;(PS:因为这个错误卡了一天)

    #include<iostream>
    #include<algorithm>
    #define max 100005
    typedef long long ll;
    using namespace std;
    int n,k,a[max],b[max];
    ll m;
    ll judge(int x) {
        int num=0;
        ll ans = 0;
        int l,r;l=r=0;
        while(l<n) {
            while(r<n&&num<k) {
                if(a[r++]>=x) {
                    num++;
                }
            }
            if(num>=k) ans += n-r+1;
            if(a[l++]>=x) num--;
            
        }
        return ans;
    }
    int main() {
        int t;
        cin>>t;
        while(t--) {
            
            cin>>n>>k>>m;
            for(int i=0; i<n; i++) {
                cin>>a[i]; b[i] = a[i];
            }
            sort(b,b+n);
            int l,r,mid; l=0, r=n-1; ll ans = 0;
            while(l<=r) {
                mid = (l+r)>>1;
                if(judge(b[mid])>=m) {
                    ans = b[mid];
                    l = mid+1;
                }else{
                    r = mid-1;
                }
            }
            cout<<ans<<endl;
        }
        return 0;
    }

    错误原因:

          通过X比较出答案,并非X为答案

          这里是逐步寻找最优解的过程,而不是精确查找

    #include<iostream>
    #include<algorithm>
    #define max 100005
    typedef long long ll;
    using namespace std;
    int n,k,a[max],b[max];
    ll m;
    ll judge(int x) {
        int num=0;
        ll ans = 0;
        int l,r;l=r=0;
        while(l<n) {
            while(r<n&&num<k) {
                if(a[r++]>=x) {
                    num++;
                }
            }
            if(num>=k) ans += n-r+1;
            if(a[l++]>=x) num--;
            
        }
        return ans;
    }
    int main() {
        int t;
        cin>>t;
        while(t--) {
            
            cin>>n>>k>>m;
            for(int i=0; i<n; i++) {
                cin>>a[i]; b[i] = a[i];
            }
            sort(b,b+n);
            int l,r,mid; l=0, r=n-1; ll ans = 0;
            while(l<=r) {
                mid = (l+r)>>1;
    //            cout<<"left="<<l<<" right="<<r<<endl;
    //            cout<<"b[mid]="<<b[mid]<<endl;
                if(judge(b[mid])==m){break;} 
                if(judge(b[mid])>m) {
                    l = mid+1;
                }else{
                    r = mid-1;
                }
            }
            cout<<b[mid]<<endl;
        }
        return 0;
    }
  • 相关阅读:
    vue+elemnet 实现自定义参数
    css 实现鼠标移上去标题向右滑动的效果
    vue 搜索关键字列表结果高亮显示
    leaflet 实现 测距、测面、清除测量的功能
    js对象的合并
    formdata的使用方法
    fromdata上传多个文件
    3.11formdata的使用
    微信小程序的自定义插件
    3.6
  • 原文地址:https://www.cnblogs.com/Lemon1234/p/11603554.html
Copyright © 2020-2023  润新知