首页 > 其他分享 >CF786c分块题解

CF786c分块题解

时间:2023-09-03 22:11:05浏览次数:42  
标签:二分 分块 int 题解 sum num 答案 CF786c 根号

CF786c分块题解

思路:

首先思考一下如果直接硬着头皮做会怎么样?
对于每一个k,我都要遍历一遍数组贪心求解ans,导致n方时间复杂度

要发现一下性质:

  1. 答案最多为ceil(n/k)。
  2. 随着k的增加,答案单调不增。
  3. 随着k的增加,答案越不容易改变(连续相同的答案越多)。

由1可知,总共的答案数量大概在根号n级别
由2可知,可以二分答案,寻找出连续一段k的答案是多少
由3可知,越到k大的地方,越容易二分出很长一段相同的答案,反之,在前面二分答案很多都是无效的
用根号n来区分前面和后面,前面暴力后面二分答案
前面时间复杂度:n * 根号n
后面时间复杂度:不会分析......
这样分析:
如果不分段的话,答案就是n * n * logn
然后答案最多根号n个,我二分又能找到一段的答案,所以应该是
n * 根号n * logn
假设我分的长度为s
那么变成了s * 根号n * logs+s * n
大概s在根号n的时候比较好

代码:

#include<bits/stdc++.h>
using namespace std;
int num[100006];
bool T[100005];
int n;
int work(int k){
    memset(T,0,sizeof(T));
    int sum = 0, cnt = 0, sta = 1;
    for(int i = 1; i <= n; ++ i){
        if(!T[num[i]]){
            T[num[i]] = 1, cnt ++;
        } 
        if(cnt > k){
            sum++, cnt = 1;
            for(int j = sta; j < i; ++ j){//如此来保证找一次用n的时间
                T[num[j]] = 0;
            } 
            T[num[i]] = 1; 
            sta = i;
        }
    }
    if(cnt){
        sum++;
    } 
    return sum;
}
int sq;
int main(){
	ios::sync_with_stdio(false);
	
	cin >> n;
	for(int i=1;i<=n;i++){
		cin >> num[i];
	}
	sq=ceil(1.0*sqrt(n));
    for(int i=1;i<=sq;i++){
        int ans=work(i);
        cout<<ans<<" ";
    }
    int now=sq+1;
    while(now<=n){
        int ans=work(now);
        int l=now;
        int r=n;
        while(l<=r-1){
            int mid=ceil(1.0*(l+r)/2);
            int ans2=work(mid);
            if(ans2<ans){
                r=mid-1;
            }
            else{
                l=mid;
            }
        }
        for(int i=now;i<=l;i++){
            cout<<ans<<" ";
        }
        now=l+1;
    }

}

标签:二分,分块,int,题解,sum,num,答案,CF786c,根号
From: https://www.cnblogs.com/linghusama/p/17675699.html

相关文章

  • 8.30 模拟赛 光和影(dream) 题解
    概括:大分类讨论。首先有个重要结论,无论是三种操作中的哪一种,他的左儿子仍然在他的左子树内,右儿子在右子树内。同时,旋转一个点一次,对他更上面的点的深度没有影响。以此,我们预处理出一个\(up_{u,0/1}\)表示将\(u\)splay到根上,对左子树和右子树深度的影响,由于上面的结论,这个东......
  • CF838D Airplane Arrangements 题解
    题意一架飞机有\(n\)个座位排成一列,有\(m\)名乘客(\(m\leqn\))依次上飞机。乘客会选择一个目标座位(两人可以选同一个目标座位),然后选择从前门或者后门上飞机,上飞机后,他们会走到自己的目标座位,如果目标座位已经有人坐了,他们会继续往前走,在走到第一个空位后坐下。如果走到最后......
  • 【题解】P2900 [USACO08MAR] Land Acquisition G
    题目链接:P2900[USACO08MAR]LandAcquisitionG我们通过题目可以得出一个较为清晰的结论:我们将所有的矩形排列起来,可以发现最后被完全包含在另一个矩形内的矩形是没有意义的。这样的话我们得到的所有矩形的并是呈阶梯状的,如下图:其中,中间的浅蓝色的边是没有意义的然后我......
  • [ABC318G] Typical Path Problem 题解
    题意给定一个\(N\)个节点和\(M\)条边组成的简单无向联通图,给定三个节点\(A,B,C\),求是否存在一条简单路径满足\(A\rightarrowB\rightarrowC\)。(\(3\leN,M\le2\times10^5\))。题解因为简单路径要求每个节点至多经过一次,故不存在合法的简单路径当且仅当存在一个......
  • 「突刺贯穿第二分块」P4117 [Ynoi2018] 五彩斑斓的世界
    很帅气!分块在线转离线,考虑每个块对于询问的贡献。维护块的max和tag分别代表最大值和减了多少。先考虑整块,\(max<2*x:\)每次暴力区间平移即可。否则对于\([1,x]\)全部加上\(x\)平移到\([x+1,x*2]\),然后区间整体减\(x\)即可。散块怎么做?暴力减,然后重构块......
  • 【动态规划】“新手动态规划合集”题解
    动态规划三要素阶段,状态,决策动态规划经典模型LIS(最长上升子序列)给定长度为\(N\)的序列\(A[i]\),求出其最长上升子序列的长度。(以不严格上升为例)阶段:已经处理的序列长度\(i\)状态:\(f[i]\)表示以\(A[i]\)结尾的LIS长度转移\[f[i]=\max\limits_{j\in\left[1,......
  • [ABC318D] General Weighted Max Matching 题解
    [ABC318D]GeneralWeightedMaxMatching题解题意  给定无向有权完全图,求最大权匹配。思路分析  注意到\(n\le16\),我考虑状压DP。  设当前点集\(S\)中最大权匹配的答案是\(f_S\),我们考虑\(S\)中“最后”一个点\(p\)(这里的“最后”一个点是指,在状压表示状态......
  • [ABC318E] Sandwiches 题解
    题意给定一个长度为\(N\)的正整数列\(A=\left(A_1,A_2,\cdots,A_N\right)\),求满足以下条件的正整数三元组\(\left(i,j,k\right)\)的数量:\(1\lei<j<k\leN\);\(A_i=A_k\);\(A_i\neqA_j\)。数据范围:\(3\leN\le3\times10^5\);\(1\leA_i......
  • CF1848B Vika and the Bridge 题解
    CF1848BVikaandtheBridge题解题目大意给个题目传送门吧,感觉题意已经很清楚了题目传送门分析(我不会告诉你我第一眼看过去是二分)因为我们只能改一块木板的颜色,所以可以考虑贪心。大概算了下复杂度,也没有问题。题解我们要去求每种颜色最大距离的最小值,那我们可以先去求......
  • 有关Vue-Cli5.X工程中ESLint组件命名检查问题解决
    个人开发环境简介,工具用的VisualStudioCode,因为每个人的开发环境不同,不可能所有解决方案通用,防止踩坑。PSF:\VueWorkSpace\vue_router_test>node-vv16.12.0PSF:\VueWorkSpace\vue_router_test>npm-v8.1.0PSF:\VueWorkSpace\vue_router_test>npmeslint-v8.1.0......