http://codeforces.com/contest/787/problem/E

题目大意:给你n块,每个块都有一个颜色,定义一个k,表示在区间[l,r]中最多有k中不同的颜色。另k=1,2,3...n,问在每一种情况下,输出能划分出的最小的段落数。

例如:

5
1 3 4 3 3
ans = 4, 2, 1, 1, 1
  1. [1], [3], [4], [3, 3]
  2. [1], [3, 4, 3, 3]
  3. [1, 3, 4, 3, 3]
  4. [1, 3, 4, 3, 3]
  5. [1, 3, 4, 3, 3]

思路:太久没写过主席树了,有点傻了

先说这题的弱化版,只对于一个k=x的情况,统计能划分成几段

其实这个问题,我们就只需要暴力一遍,定义lb=1,然后一直往后面暴力,for(rb; rb <=n; rb++)然后加入节点就用segment tree来维护。如果color的数目达到了k,我们就移动lb,让lb一直移动到等于rb,并在移动的同时删除线段树上的信息即可。所以复杂度是O(n*logn)

那么对于每一个k,我们可以利用上面的思路来解决这个问题

下面这一段来自这个人的:http://kugwzk.info/index.php/archives/2296

首先不管怎么说,肯定是能尽量拿尽量拿,保证一个队尽可能的长。然后我们在枚举k的时候,其实已经有了一个O(nlogn)的复杂度了:因为n+n/2+n/3+....n/n=nlogn。。。所以我们必须要在logn的时间内找到对于一个位置i而言,最大的一个j,满足i到j的颜色数不超过k。那也就需要知道[i,j]这样一段区间有多少个不同的颜色。
可以主席树维护一下这个东西,我们从位置1开始维护,用一个pre记录下来每种颜色的上一个位置在哪里。第i棵主席树表示的含义就是从1-i这样一段区间内的不同的颜色数目。也就是每个节点都存一下他所代表的区间内的颜色个数。因为我们记录下来了之前那种颜色的位置,所以新加入i位置的时候,在那个位置上减去1,在i位置上加上1.这样每次修改O(logn)个节点。从而满足统计出来1-i的颜色个数。

然后我这里在主席树上面找的方法就是找还需要剩下多少颜色

//看看会不会爆int!数组会不会少了一维!
//取物问题一定要小心先手胜利的条件
#include <bits/stdc++.h>
using namespace std;
#pragma comment(linker,"/STACK:102400000,102400000")
#define LL long long
#define ALL(a) a.begin(), a.end()
#define pb push_back
#define mk make_pair
#define fi first
#define se second
#define haha printf("haha\n")
const int maxn = 1e5 + ;
int n;
struct Tree{
int lb, rb, val;
}tree[maxn << ];
int pre[maxn], a[maxn], head[maxn];
int k, tot; int update(int pos, int l, int r, int o, int cost){
int k = ++tot;
tree[k] = tree[o];
tree[k].val += cost;
if (l == pos && r == pos) return k;
int mid = (l + r) / ;
if (pos <= mid) tree[k].lb = update(pos, l, mid, tree[o].lb, cost);
if (pos > mid) tree[k].rb = update(pos, mid + , r, tree[o].rb, cost);
return k;
} int query(int l, int r, int o, int cost){
if (l == r) return l;
int mid = (l + r) / , lb = tree[o].lb, rb = tree[o].rb;
if (tree[lb].val >= cost) return query(l, mid, lb, cost);
return query(mid + , r, rb, cost - tree[lb].val);
} int main(){
cin >> n;
for (int i = ; i <= n; i++){
scanf("%d", a + i);
head[i] = update(i, , n, head[i - ], );
if (pre[a[i]]) head[i] = update(pre[a[i]], , n, head[i], -);
pre[a[i]] = i;
}
for (int i = ; i <= n; i++){
int ans = , pos = n;
while (true){///因为要找i个不一样的颜色的,就要找个数为n-i个的
int need = tree[head[pos]].val - i;
if (need <= ){ans++; break;}
pos = query(, n, head[pos], need);
ans++;
}
printf("%d ", ans);
}
cout << endl; return ;
}

维护前面的position+主席树 Codeforces Round #406 (Div. 2) E的更多相关文章

  1. 线段树 Codeforces Round #197 (Div. 2) D. Xenia and Bit Operations

    题目传送门 /* 线段树的单点更新:有一个交叉更新,若rank=1,or:rank=0,xor 详细解释:http://www.xuebuyuan.com/1154895.html */ #inclu ...

  2. set+线段树 Codeforces Round #305 (Div. 2) D. Mike and Feet

    题目传送门 /* 题意:对于长度为x的子序列,每个序列存放为最小值,输出长度为x的子序列的最大值 set+线段树:线段树每个结点存放长度为rt的最大值,更新:先升序排序,逐个添加到set中 查找左右相 ...

  3. 【转】Codeforces Round #406 (Div. 1) B. Legacy 线段树建图&&最短路

    B. Legacy 题目连接: http://codeforces.com/contest/786/problem/B Description Rick and his co-workers have ...

  4. Codeforces #Round 406(Div.2)

    来自FallDream的博客,未经允许,请勿转载,谢谢. ------------------------------------------------------- 大家好,我是一个假人.在学习O ...

  5. 【Codeforces Round #406 (Div. 2)】题解

    The Monster 签到题,算一下b+=a和d+=c,然后卡一下次数就可以了. Not Afraid 只要一组出现一对相反数就是安全的. Berzerk 题意:[1,n],两个人轮流走,谁能走到1 ...

  6. Codeforces Round #406 (Div. 1) B. Legacy 线段树建图跑最短路

    B. Legacy 题目连接: http://codeforces.com/contest/786/problem/B Description Rick and his co-workers have ...

  7. Codeforces Round #406 (Div. 2) D. Legacy 线段树建模+最短路

    D. Legacy time limit per test 2 seconds memory limit per test 256 megabytes input standard input out ...

  8. 区间->点,点->区间,线段树优化建图+dijstra Codeforces Round #406 (Div. 2) D

    http://codeforces.com/contest/787/problem/D 题目大意:有n个点,三种有向边,这三种有向边一共加在一起有m个,然后起点是s,问,从s到所有点的最短路是多少? ...

  9. Codeforces Round #406 (Div. 2) D. Legacy (线段树建图dij)

    D. Legacy time limit per test 2 seconds memory limit per test 256 megabytes input standard input out ...

随机推荐

  1. Thunder——互评beta版本

    基于NABCD和spec评论作品 Hello World!:http://www.cnblogs.com/vector121/p/7922989.html 欢迎来怼:http://www.cnblog ...

  2. Java:有关自定数组的学习

    Java:有关==自定数组==的学习 在 ==<Java程序设计与数据结构教程>== 里我在==P212~P213==页看到一个GradeRange的程序,它用的数组是自定设定的Grade ...

  3. unix系统内核优点

    1.可靠性高 unix的可靠性2.伸缩性强 unix的伸缩性3.开放性好 unix的开放性4.网络功能强 unix的网络功能这是UNIX系统的又一重要特色,特别是作为Internet网络技术基础的TC ...

  4. Markdown的基本语法

    Markdown 是一种轻量级的「标记语言」,它的优点很多,目前也被越来越多的写作爱好者,撰稿者广泛使用.看到这里请不要被「标记」.「语言」所迷惑,Markdown 的语法十分简单.常用的标记符号也不 ...

  5. 阿里云服务器内部dns可能出错

    今天部署一个阿里云服务器,所有配置项都改好了,就是连接不上本机. 反复查找,防火墙端口和网卡接口都配置对了,selinux也关闭了,但就是连接不上阿里云内网的ip. 由于连接是本机,把ip填写为127 ...

  6. 使用fprof基本步骤

    $erl -name a@localhost -setcookie abc -remsh b@localhost >fprof:trace([start, {file, "/home/ ...

  7. Dsyy的第一篇博文~

    2017-08-07  周一  晴热热热热热 咳咳,很多人看到dsyy第一反应是什么意思?当然是大神媛媛!显然不是些(diao)(si)yy.(da)(si)yy...的别义,咋有点此地无银三百两的感 ...

  8. 【Mark】Android应用开发SharedPreferences存储数据的使用方法

    Android应用开发SharedPreferences存储数据的使用方法 SharedPreferences是Android中最容易理解的数据存储技术,实际上SharedPreferences处理的 ...

  9. PHP 在windows下配置sendmail,通过 mail() 函数发送邮件

    php mail()函数在windows不能用,需要安装sendmail. 1. 从http://glob.com.au下载sendmail.zip 2. 解压sendmail.zip到目录下(最好使 ...

  10. docker+mesos+marathon

    前言 (Core) [root@docker-slave ~]# uname -r 3.10.0-229.4.2.el7.x86_64 [root@docker-slave ~]# uname -m ...