zoukankan      html  css  js  c++  java
  • ZOJ 3790 Consecutive Blocks [排序+扫描]

    There are N (1 ≤ N ≤ 105) colored blocks (numbered 1 to N from left to right) which are lined up in a row. And the i-th block's color is Ci (1 ≤ Ci ≤ 109). Now you can remove at most K (0 ≤ KN) blocks, then rearrange the blocks by their index from left to right. Please figure out the length of the largest consecutive blocks with the same color in the new blocks created by doing this.

    For example, one sequence is {1 1 1 2 2 3 2 2} and K=1. We can remove the 6-th block, then we will get sequence {1 1 1 2 2 2 2}. The length of the largest consecutive blocks with the same color is 4.

    Input

    Input will consist of multiple test cases and each case will consist of two lines.For each test case the program has to read the integers N and K, separated by a blank, from the first line. The color of the blocks will be given in the second line of the test case, separated by a blank. The i-th integer means Ci.

    Output

    Please output the corresponding length of the largest consecutive blocks, one line for one case.

    Sample Input

    8 1
    1 1 1 2 2 3 2 2
    

    Sample Output

    4
    

    给n个数,最多可以删掉k个,求连续相同数字的最长长度。


    先进行一下预处理,把相同连续的数字都变成一个个块,标记好块的长度和起止位置,然后排序,把相同数字的块都放到一起。最后按各个数字分别扫描,记录最长的长度。

    用两个指针begin和end来表示相同的数字区间,i从begin一直扫到end,添加的时候将i位置的块加进去,当区间距离和大于k时从begin开始删。


    对于样例,经过预处理的得到以下信息


    数字 连续个数 块起点 块终点
    1 3 1 3
    2 2 4 5
    2 2 7 8
    3 1 6 6


    扫描到1,可得到最大连续个数3。

    扫描到2,先是[4,5]区间,再到[7,8]区间,两区间距离是1<=k,可以继续。数字2扫描完成,最长长度是4。

    扫描到3,只有1个。


    假设k = 0,扫描2的时候,先加上[4,5],再加上[7,8]时,两块距离大于k,需将[4,5]删除。


    #include<algorithm>
    #include<cassert>
    #include<cmath>
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    #define rep(i,f,t) for(int i = (f), _end = (t); i <= _end; ++i)
    #define clr(c,x) memset(c,x,sizeof(c));
    #define debug(x) cout<<"debug  "<<x<<endl;
    const int INF = 0x3f3f3f3f;
    
    //*******************************************************************************
    const int maxn = 100000 + 10;
    struct Node{
        int num,cnt,from,to;
        Node (int nu=0):num(nu),from(maxn){}
        bool operator < (const Node & n2)const {
            if(num == n2.num)return from < n2.from;
            return num < n2.num;
        }
    }a[maxn];//存放分段后的数据
    
    int len;
    int n,k;
    int dt[maxn]; //存放输入的数据
    int ans;
    
    void pre(){
        int cur = -1;
        int f = 1;
        len = 0;
        dt[n+1] = 0;
        rep(i,1,n+1){
            if(cur != dt[i])
            {
                if(cur < 0){ //第一个元素
                    cur = dt[i];
                    continue;
                }
                ++len;
                a[len].num = cur;
                a[len].cnt = i - f;
                a[len].from = f;
                a[len].to = i - 1;
                f = i;
                cur = dt[i];
            }
        }
    }
    //第i段与第i-1段的距离
    inline int getdis(int i){ return a[i].from - a[i-1].to - 1; }
    
    void solve(){
        int begin = 1,end;
        do{
            end = upper_bound(a+begin,a+len+1, Node(a[begin].num)) - a;
            int i = begin;
            int m = 0;
            int dis = 0;
            a[i-1].to = a[i].from-1; //为了下面计算新元素距离的方便
            while(i < end){
                //add
                while(i < end){
                    dis += getdis(i);
                    m += a[i].cnt;
                    ++i;
                    if(dis > k)break; //间隔大于k,连不起来了
                    ans = max(ans,m);
                }
                //delete
                while(dis > k){
                    dis -= getdis(begin+1);
                    m -= a[begin].cnt;
                    ++begin;
                }
                ans = max(ans,m);
                assert(begin <= i);
            }
            begin = end; //下一个数字
        }while(begin <= len);
    }
    int main(){
        while(scanf("%d%d",&n,&k) == 2){
            len = 0;
            rep(i,1,n)scanf("%d",dt+i);
            pre();
            sort(a+1,a+len+1);
            ans = 0;
            solve();
            printf("%d
    ",ans);
        }
        return 0;
    }
    



    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    在C语言中,double、long、unsigned、int、char类型数据所占字节数
    C++基础之头文件和源文件的关系
    Activity与Fragment数据传递之Activity从Fragment获取数据 分类: Android 2015-07-02 09:56 12人阅读 评论(0) 收藏
    Activity与Fragment数据传递之Fragment从Activity获取数据 分类: Android 2015-07-01 14:12 17人阅读 评论(0) 收藏
    Java反射机制和对象序列化 分类: Java 2015-06-26 12:08 21人阅读 评论(0) 收藏
    Android通过播放多张图片形成一个动画 分类: Android 2015-04-24 14:05 16人阅读 评论(0) 收藏
    jvm参数的配置、垃圾回收器的配置
    selenium2工作原理
    LeetCode#1 Two Sum
    LeetCode#27 Remove Element
  • 原文地址:https://www.cnblogs.com/DSChan/p/4861994.html
Copyright © 2011-2022 走看看