题意:给你一个序列,让你求出对于所有区间<i, j>的mex和,mex表示该区间没有出现过的最小的整数。

思路:从时限和点数就可以看出是线段树,并且我们可以枚举左端点i, 然后求出所有左端点为i的区间内mex值的和。

先把数插满,然后先询问后删除当前最左边的断点i。而且显然线段树里面保存的是mex值,而且这个序列是非递减的。

分析:我们先预处理出对于右端点为i的所有<1,i>的mex,分别插入线段树的i位置。然后每次删除最左边的左端点i

,假如当前我们要删除a[i] ,我们找到它之后第一个位置j满足a[i] == a[j],  那么区间i------j-1里面的所有mex都要更新,取线段树内的值和a[i]的最小值。 实际操作我们只要找到第一个比a[i]的位置l,  r = j-1,  更新<l,r>之间的mex为a[i]即可。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
#define ls rt<<1
#define rs rt<<1|1
#define Mid int m = l+r>>1
const int maxn = 2000006;
int next[maxn], pre[maxn], n;
int a[maxn], mex;
bool vis[maxn];
ll sum[maxn<<2];
int mx[maxn<<2], col[maxn<<2];
void build(int l=1, int r=n, int rt=1) {
col[rt] = -1;
sum[rt] = 0;
mx[rt] = 0;
if(l == r) return;
Mid;
build(lson);
build(rson);
}
inline void down(int l, int r, int rt) {
if(~col[rt]) {
col[ls] = col[rs] = col[rt];
Mid;
sum[ls] = (ll)(m-l+1)*col[rt];
mx[ls] = mx[rs] = col[rt];
sum[rs] = (ll)(r-m)*col[rt];
col[rt] = -1;
}
}
inline void up(int rt) {
sum[rt] = sum[ls] + sum[rs];
mx[rt] = max(mx[ls], mx[rs]);
}
void update(int L, int R, int v, int l=1, int r=n, int rt=1) {
if(L <= l && r <= R) {
col[rt] = mx[rt] = v;
sum[rt] = (ll)(r-l+1)*v;
return;
}
Mid; down(l, r, rt);
if(L <= m) update(L, R, v, lson);
if(R > m) update(L, R, v, rson);
up(rt);
}
ll query(int L, int R, int l=1, int r=n, int rt=1) {
if(L <= l && r <= R)
return sum[rt];
Mid; down(l, r, rt);
ll ret = 0;
if(L <= m) ret += query(L, R, lson);
if(R > m) ret += query(L, R, rson);
up(rt);
return ret;
}
int find(int v, int l=1, int r=n, int rt=1) {
if(mx[rt] <= v) return n+1;
if(l == r) return l;
Mid; down(l, r, rt);
if(mx[ls] > v) return find(v, lson);
else return find(v, rson);
}
int main() {
int i, j;
while(~scanf("%d", &n) && n) {
for(i = 1; i <= n; i++) {
scanf("%d", &a[i]);
pre[i] = vis[i] = 0;
next[i] = n+1;
}
pre[0] = vis[0] = 0;
for(i = 1; i <= n; i++)
if(a[i] <= n) {
if(pre[a[i]])
next[pre[a[i]]] = i;
pre[a[i]] = i;
}
build();
mex = 0;
for(i = 1; i <= n; i++) {
if(a[i] <= n){
vis[a[i]] = 1;
while(vis[mex]) mex++;
}
update(i, i, mex);
}
ll ans = 0;
for(i = 1; i <= n; i++) {
ans += query(i, n);
if(a[i] <= mex) {
int l = max(find(a[i]), i);
int r = next[i]-1;
if(l <= r) update(l, r, a[i]);
}
}
printf("%I64d\n", ans);
}
return 0;
}
/*
3
0 10000 20000
*/

[置顶] hdu4747 Mex 线段树的更多相关文章

  1. HDU-4747 Mex 线段树

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4747 题意:求一个数列中,所有mex(L,R)的和. 注意到mex是单调不降的,那么首先预处理出mex ...

  2. hdu 4747 mex 线段树+思维

    http://acm.hdu.edu.cn/showproblem.php?pid=4747 题意: 我们定义mex(l,r)表示一个序列a[l]....a[r]中没有出现过得最小的非负整数, 然后我 ...

  3. BZOJ.3585.mex(线段树)

    题目链接 题意:多次求区间\(mex\). 考虑\([1,i]\)的\(mex[i]\),显然是单调的 而对于\([l,r]\)与\([l+1,r]\),如果\(nxt[a[l]]>r\),那么 ...

  4. bzoj 3585 mex - 线段树 - 分块 - 莫队算法

    Description 有一个长度为n的数组{a1,a2,...,an}.m次询问,每次询问一个区间内最小没有出现过的自然数. Input 第一行n,m. 第二行为n个数. 从第三行开始,每行一个询问 ...

  5. HDU-4747 二分+线段树

    题意:给出长度为n的序列,问任两个区间的mex运算结果的总和. 解法:直接讲线段树做法:我们注意到mex(1,1),mex(1,2),mex(1,3)...mex(1,i)的结果是单调不减的,那么我们 ...

  6. Codeforces 1083C Max Mex [线段树]

    洛谷 Codeforces 思路 很容易发现答案满足单调性,可以二分答案. 接下来询问就转换成判断前缀点集是否能组成一条链. 我最初的想法:找到点集的直径,判断直径是否覆盖了所有点,需要用到树套树,复 ...

  7. 【bzoj3585】mex 线段树 mex,sg

    Description 有一个长度为n的数组{a1,a2,…,an}.m次询问,每次询问一个区间内最小没有出现过的自然数. Input 第一行n,m. 第二行为n个数. 从第三行开始,每行一个询问l, ...

  8. CF1083C Max Mex 线段树

    题面 CF1083C Max Mex 题解 首先我们考虑,如果一个数x是某条路径上的mex,那么这个数要满足什么条件? 1 ~ x - 1的数都必须出现过. x必须没出现过. 现在我们要最大化x,那么 ...

  9. [置顶] hdu 1890 伸展树区间翻转

    题意: 给你n个数,每次先输出第i大的数的位置(如果有多个,选下标小的那个),然后每次将第i个位置到第i大的数所在位置之间的数进行翻转. 思路:输入的数组可能有多个相同的值,我们可以进行两次排序把数组 ...

随机推荐

  1. css3的盒子模型布局

    写在前面的话: css3盒子布局,可以更简单直观的均分页面某一个div,并且还可以达到均分后的每一个元素中的内容上下居中.左右居中,但是该模型对浏览器的版本有要求: { display: -webki ...

  2. 利用Azure Automation实现云端自动化运维(4)

    在上述基本准备工作做完后,wo们看看如何实现利用Azure Automation实现定时自动开关机的操作,这种场景非常适合Dev/Test环境,因为Azure的虚拟机是按照分钟收费的,所以我们可以在开 ...

  3. Linux下 nginx + 最新版php5.5 安装配置详解

    1.nginx的安装: 首先nginx的安装需要依赖最基础的三个包,这里面我们不设计更多的扩展模块,只是安装最基础的三个包, zlib 此包主要是对http内容进行gzip压缩,减少网络传输流量 PC ...

  4. oracle 创建表空间详细介绍

    注意点: 1.如果在PL/SQL 等工具里打开的话,直接修改下面的代码中[斜体加粗部分]执行 2.确保路径存在,比如[D:\oracle\oradata\Oracle9i\]也就是你要保存文件的路径存 ...

  5. listvew加载更多

    http://bbs.51cto.com/thread-968277-1.html 又是新的一周的开始,上午自己写了上拉加载更多数据的demo,嘿嘿这里和大家分享.   android开发中,list ...

  6. NFC的安全性

    NFC近距离无线技术具有快捷.易用.安全等特性,其中安全是支付行业最关心的特性. 众所周知传统磁条银行卡的账号信息,是记录在磁条中,当进行刷卡交易时,POS机将交易金额,银行卡中的账号信息以及用户输入 ...

  7. 使用httpwatch抓包

    httpwatch抓包工具是MS的ie自带的一个插件. 但是千里之行始于足下,所以先来利用httpwatch抓一些包来分析分析. 打开IE,快捷键shift+F2打开httpwatch. 如下图: 本 ...

  8. 关于jqueryUI里的拖拽排序

    主要参考http://jsfiddle.net/KyleMit/Geupm/2/  (这个站需要FQ才能看到效果) 其实是jqueryUI官方购物车拖拽添加例子的增强版,就是在拖拽的时候增加了排序 这 ...

  9. Rescue(bfs)

    Rescue Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 65536/32768K (Java/Other) Total Submis ...

  10. Segment FRAM_DATA must be defined in a segment definition option (-Z, -b or -P)

    1. 网上说这个回答是 协议栈和IAR版本号不一样,这算什么神马问题 2. 网上的解决的方法是改动 options-> link -> config -> 改动里面的连接文件,可是怎 ...