题意:给你n个数,问最少能把这n个数分成连续的几段,且每段中不同的个数小于等于k个,输出k从1到n的答案。
分析:我们知道i~(i,,,n)的不同数的个数肯定是递增的,所以对于每个i,我们可以通过二分得出一个最大的j使[i,j]中不同的数个数<=k。那么问题的关键在于,如何知道[i,j]这样一个区间中,不同的数的个数。
我们可以利用主席树,以root[i]为顶点的线段树存的是,[i,n]中不同的数个数,对于每颗树,将每个第一次出现的数的位置 置为1,其他重复出现的位置 置为0。
那么,对于每个k,刚开始我们位于root[1],二分找出值为k+1的位置r,ans[k]++,并将当前位置置成root[r],这样,我们面对的就是[r,n]这段数,直到r>n停止。
代码中:ed[i]表示最先出现i的位置,Next[i]表示在i位置的数下一次出现在哪个位置。
以下是代码: