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
  • 相关阅读:
    线性回归的从零开始实现
    比赛总结
    计数学习笔记
    DP计数问题
    多项式学习笔记
    数据结构学习笔记
    子集运算学习笔记
    待学习
    ICPC2018焦作 题解
    ICPC2018焦作 H题 Can You Solve the Harder Problem?
  • 原文地址:https://www.cnblogs.com/Jessie-/p/10527865.html
Copyright © 2011-2022 走看看