zoukankan      html  css  js  c++  java
  • CF786C Till I Collapse

    题目大意:

    对于一个序列,倘若一个区间内最多能发 $k$ 个不同的数,那么这个序列最少被划分成几个区间。

    输出 $k$ 为 $1$ ~ $n$ 的答案。

    思路:

    其实会有连续一段不同的 $k$ 得到相同的答案,所以我们对于每段 $k$ 向下递归,如果左端点的答案和右端点的答案相同,那么就可以确定这一整段区间的答案。

    以下代码: 

    #include<bits/stdc++.h>
    #define il inline
    #define _(d) while(d(isdigit(ch=getchar())))
    using namespace std;
    const int N=1e5+5;
    bool vis[N];
    int n,a[N],ans[N];
    il int read(){
        int x,f=1;char ch;
        _(!)ch=='-'?f=-1:f;x=ch^48;
        _()x=(x<<1)+(x<<3)+(ch^48);
        return f*x;
    }
    il int getans(int k){
        int num=0,res=0,l=1;
        for(int i=1;i<=n;i++){
            if(!vis[a[i]]){
                num++;
                if(num>k){
                    num=1;
                    for(int j=l;j<i;j++)vis[a[j]]=0;
                    res++;l=i;
                }
                vis[a[i]]=1;
            }
        }
        for(int i=1;i<=n;i++)vis[i]=0;
        return res+1;
    }
    il void solve(int l,int r){
        if(!ans[l])ans[l]=getans(l);
        if(!ans[r])ans[r]=getans(r);
        if(ans[l]==ans[r]){
            for(int i=l;i<=r;i++)ans[i]=ans[l];
            return;
        }
        int mid=(l+r)>>1;
        solve(l,mid);solve(mid+1,r);
    }
    int main()
    {
        n=read();
        for(int i=1;i<=n;i++)a[i]=read();
        solve(1,n);
        for(int i=1;i<=n;i++)printf("%d ",ans[i]);
        return 0;
    }
    View Code
  • 相关阅读:
    Apache Pig的前世今生
    openssl之EVP系列之6---EVP_Encrypt系列函数编程架构及样例
    P3388 【模板】割点(割顶)
    让priority_queue支持小根堆的几种方法
    2017.11.7解题报告
    一个例子教你如何与出题人斗智斗勇
    debug
    树上倍增求LCA及例题
    素数的筛法
    Catalan卡特兰数入门
  • 原文地址:https://www.cnblogs.com/Jessie-/p/10527865.html
Copyright © 2011-2022 走看看