Codeforces 786C. Till I Collapse 主席树
题目大意:
给定一个长度为\(n\)的序列,要求将其划分为最少的若干段使得每段中不同的数字的种数不超过\(k\).
对于 \(k = 1 .. n\)输出所有的答案.
\(n \leq 10^5\)
题解:
考虑最坏情况下会分成多少段.
最坏分成\(\frac{n}{k}\)段。
所以对于每种\(k\)将其段数加起来。
有\(O(\sum_{k=1}^n\frac{n}{k})= O(n\log n)\)
所以我们可以考虑每次找出下一个端点进行转移。
复杂度为\(O(\text{转移}nlogn)\)
对于每次转移我们要找到最大的一个元素使得从当前点向右经过的不同的数字种数\(\leq k\)
假设说我们有一个数组\(f_{p,i}\)表示从\(p\)开始往后\(i\)是否是第一次出现。
那么我们就可以通过在线段树上二分的方式在\(\log n\)的时间确定这个坐标。
考虑对每一个\(p\)建立\(f_{p,i}\)的线段树。
然后发现\(f_p\)与\(f_{p+1}\)只有两个元素不同的区别。
所以可以建立可持久化线段树完成这个东西的维护。
复杂度\(O(n\log^2n)\)
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
inline void read(int &x){
x=0;char ch;bool flag = false;
while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
}
#define rg register int
#define rep(i,a,b) for(rg i=(a);i<=(b);++i)
#define per(i,a,b) for(rg i=(a);i>=(b);--i)
const int maxn = 100010;
struct Node{
Node *ch[2];
int num;
void update(){
num = ch[0]->num + ch[1]->num;
}
}mem[maxn*40],*null,*it,*root[maxn];
inline void init(){
it = mem;null = it++;
null->ch[0] = null->ch[1] = null;
null->num = 0;root[0] = null;
}
Node* modify(Node *rt,int l,int r,int pos,int val){
Node *p = it++;*p = *rt;
if(l == r){
p->num = val;
return p;
}
int mid = l+r >> 1;
if(pos <= mid) p->ch[0] = modify(p->ch[0],l,mid,pos,val);
else p->ch[1] = modify(p->ch[1],mid+1,r,pos,val);
p->update();return p;
}
inline int find(Node *p,int l,int r){
if(l == r && p->num != 0) return -1;
if(l == r) return l;
int mid = l+r >> 1;
if(p->ch[0]->num == 0) return max(mid,find(p->ch[1],mid+1,r));
else return find(p->ch[0],l,mid);
}
int query(Node *p,int l,int r,int k){
if(l == r) return l;
int mid = l+r >> 1;
if(k > p->ch[0]->num){
k -= p->ch[0]->num;
return query(p->ch[1],mid+1,r,k);
}else if(k < p->ch[0]->num) return query(p->ch[0],l,mid,k);
else return max(mid,find(p->ch[1],mid+1,r));
}
int nx[maxn],la[maxn],ws[maxn];
int a[maxn],n;
inline int solve(int k){
int pos = 1,x,ans = 0;
while(pos <= n){
x = query(root[pos],1,n,min(k,n-pos+1));
pos = x+1;++ ans;
}return ans;
}
int main(){
read(n);
rep(i,1,n) read(a[i]);
memset(ws,-1,sizeof ws);
rep(i,1,n){
la[i] = ws[a[i]];
ws[a[i]] = i;
}
memset(ws,-1,sizeof ws);
per(i,n,1){
nx[i] = ws[a[i]];
ws[a[i]] = i;
}
init();
root[1] = root[0];
rep(i,1,n){
if(la[i] == -1) root[1] = modify(root[1],1,n,i,1);
}
rep(i,2,n){
root[i] = modify(root[i-1],1,n,i-1,0);
if(nx[i-1] != -1) root[i] = modify(root[i],1,n,nx[i-1],1);
}
rep(k,1,n){
printf("%d",solve(k));
if(k != n) putchar(' ');
else putchar('\n');
}
return 0;
}
Codeforces 786C. Till I Collapse 主席树的更多相关文章
- Codeforces 786C Till I Collapse(树状数组+扫描线+倍增)
[题目链接] http://codeforces.com/contest/786/problem/C [题目大意] 给出一个数列,问对于不同的k,将区间划分为几个, 每个区间出现不同元素个数不超过k时 ...
- Codeforces 786C Till I Collapse
题意: 给出一个长度为n的序列,每个数值在1-n之间且为整数,现在要把这个序列划分为若干段,使得每一段的颜色种数不超过k,求最少的区间数目.对于从1到n的n种k的取值,分别输出这时的最少区间数目. 分 ...
- 【CodeForces】960 F. Pathwalks 主席树+动态规划
[题目]F. Pathwalks [题意]给定n个点m条边的有向图,可能不连通有重边有自环.每条边有编号 i 和边权 wi ,求最长的路径(可以经过重复节点)满足编号和边权都严格递增.n,m,wi&l ...
- CodeForces - 597C:Subsequences (主席树+DP)
For the given sequence with n different elements find the number of increasing subsequences with k + ...
- Codeforces 833B The Bakery(主席树 + 决策单调性优化DP)
题目链接 The Bakery 题目大意:目标是把$n$个数分成$k$组,每个组的值为这个组内不同的数的个数,求$k$个组的值的和的最大值. 题目分析: 这道题我的解法可能和大众解法不太一样……我用主 ...
- Codeforces 813E Army Creation(主席树)
题目链接 Educational Codeforces Round 22 Problem E 题意 给定一个序列,$q$次查询,询问从$l$到$r$中出现过的数字的出现次数和$k$取较小值后的和 ...
- Till I Collapse CodeForces - 786C (主席树区间加,二分最小值)
大意: 给定序列, 将序列划分为若干段, 使得每段不同数字不超过k, 分别求出k=1...n时的答案. 考虑贪心, 对于某个k 从1开始, 每次查询最后一个颜色数<=k的点作为一个划分, 直到全 ...
- 主席树[可持久化线段树](hdu 2665 Kth number、SP 10628 Count on a tree、ZOJ 2112 Dynamic Rankings、codeforces 813E Army Creation、codeforces960F:Pathwalks )
在今天三黑(恶意评分刷上去的那种)两紫的智推中,突然出现了P3834 [模板]可持久化线段树 1(主席树)就突然有了不详的预感2333 果然...然后我gg了!被大佬虐了! hdu 2665 Kth ...
- Codeforces Round #276 (Div. 1) E. Sign on Fence (二分答案 主席树 区间合并)
链接:http://codeforces.com/contest/484/problem/E 题意: 给你n个数的,每个数代表高度: 再给出m个询问,每次询问[l,r]区间内连续w个数的最大的最小值: ...
随机推荐
- AJAX实现三级联动
省市区三级联动插件: 主页面:为方便使用,不用写过多代码,只写一个id为sanji的div,若别的页面要用,只需写一个id为sanji的div,加载上jQuery与sanji.js文件即可 <! ...
- sequence.c
/* * sequence.c */ #include <stdio.h> #include <memory.h> /* * SM3算法产生的哈希值大小(单位:字节) */ # ...
- Linux Shell编程 条件判断语法
if条件判断语句 单分支 if 条件语句 语法格式: if [条件判断式];then 程序 fi 或者 if [条件判断式] then 程序 fi 在使用单分支 if 条件查询时需要注意几点: if ...
- Linux用户和用户组管理 用户组管理命令
添加用户组命令:groupadd 命令格式: [root@localhost ~]# groupadd [选项] 组名 选项: 选项 选项说明 -g GID 指定组ID: 修改用户组命令:groupm ...
- 【FAQ系列】Relay log 导致复制启动失败
今天在使用冷备份文件重做从库时遇到一个报错,值得研究一下. 版本:MySQL5.6.27 一.报错现象 dba:(none)> start slave; ERROR (HY000): Slave ...
- finally中的return
周五晚6点下班去面试,出了一份笔试题,看到第一题有些蒙了,虽然以前遇到过类似的问题,但并没有留心记一下,觉得没人会这样写代码,但实际上没有面试题中是有的. 1,有在try块中执行不到finally的情 ...
- debian内核代码执行流程(二)
继续上一篇文章<debian内核代码执行流程(一)>未完成部分. acpi_bus_init调用acpi_initialize_objects,经过一系列复杂调用后输出下面信息: [ IN ...
- win10 x64下的DNW驱动不完全安装方法【转】
本文转载自:https://blog.csdn.net/sihaiwenshu/article/details/52503550 一.起因 最新心血来潮想学ARM,JZ2440开发板买回来后就开始折腾 ...
- 关于在windows命令提示符cmd下运行Java程序的问题
1. win+R出现cmd运行窗口,输入Java源码文件名运行时,错误: 找不到或无法加载主类... 问题背景:我已经配置好了Java环境(安装路径PATH,JAVA_HOME已装好,cmd运行jav ...
- Kubernetes Kube-proxy
Kube-proxy主要负责Service的实现. kube-proxy enables the Kubernetes service abstraction by maintaining netwo ...