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;
    }
    



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

  • 相关阅读:
    Python数据类型文件
    Python应用程序之画图本
    opengl 学习笔记1
    圆柱面的法向量
    opengl笔记2(二次曲面的纹理映射)
    正则表达式(一)
    cocos2d的配置
    ogre配置方法
    elipse常用快捷键
    正则表达式(二)
  • 原文地址:https://www.cnblogs.com/DSChan/p/4861994.html
Copyright © 2011-2022 走看看