题目大意:给一个长度为n的整数序列,定义mex(i,j)表示区间[i,j]中没有出现过的最小非负整数,求sigma(mex(i,j)),即序列中所有连续非空子区间的mex之和。

题目分析:

answer=mex(1,1)+mex(1,2)...mex(1,n)
+ mex(2,2)...mex(2,n)
.
.
.
+ mex(n,n)。

  初始时,用线段树的叶子节点维护mex(1,i),将a(1)从序列中拿去后,将叶子节点的维护信息更新为mex(2,i),以此类推...没更新一次,便求一次区间和,总和即为答案。

  当拿掉a(i)后,只有a(k)以前的mex(i+1,j)将会受到影响,其中k>i并且a(i)=a(k)。

  当i+1<=j<k时,如果mex(i,j)>a(i),那么mex(i+1,j)=a(i),否则mex(i+1,j)=mex(i,j)。显然,当 i 固定时,mex(i,j)关于 j 单调不减。所以,mex(i,j)>a(i)的将会是一段区间。

代码如下:

# include<bits/stdc++.h>
using namespace std;
# define LL long long
# define mid (l+(r-l)/2) const int N=200000; int a[N+5];
int mex[N+5];
int nxt[N+5];
LL tr[N*4+5];
LL lazy[N*4+5];
int maxn[N*4+5]; inline void getMex(int n)
{
map<int,int>mp;
map<int,int>f;
fill(nxt,nxt+1+n,n+1);
int m=0;
for(int i=1;i<=n;++i){
mp[a[i]]=1;
while(mp[m]) ++m;
mex[i]=m;
if(f[a[i]])
nxt[f[a[i]]]=i;
f[a[i]]=i;
}
} inline void pushUp(int rt)
{
tr[rt]=tr[rt<<1]+tr[rt<<1|1];
maxn[rt]=max(maxn[rt<<1],maxn[rt<<1|1]);
} inline void pushDown(int rt,int l,int r)
{
if(lazy[rt]!=-1){
lazy[rt<<1]=lazy[rt<<1|1]=lazy[rt];
maxn[rt<<1]=maxn[rt<<1|1]=lazy[rt];
tr[rt<<1]=lazy[rt]*(LL)(mid-l+1);
tr[rt<<1|1]=lazy[rt]*(LL)(r-mid);
lazy[rt]=-1;
}
} inline void build(int rt,int l,int r)
{
lazy[rt]=-1;
if(l==r){
tr[rt]=mex[l];
maxn[rt]=mex[l];
}else{
build(rt<<1,l,mid);
build(rt<<1|1,mid+1,r);
pushUp(rt);
}
} inline int query_up(int rt,int l,int r,int L,int R,int x)
{
if(l==r){
if(tr[rt]<x) return 0;
return l;
}
pushDown(rt,l,r);
if(L<=mid&&x<maxn[rt<<1]){
int k=query_up(rt<<1,l,mid,L,R,x);
if(k>0) return k;
}
if(R>mid&&x<maxn[rt<<1|1]){
int k=query_up(rt<<1|1,mid+1,r,L,R,x);
if(k>0) return k;
}
return 0;
} inline void update(int rt,int l,int r,int L,int R,int x)
{
if(L<=l&&r<=R){
lazy[rt]=x;
tr[rt]=(LL)x*(LL)(r-l+1);
maxn[rt]=x;
}else{
pushDown(rt,l,r);
if(L<=mid) update(rt<<1,l,mid,L,R,x);
if(R>mid) update(rt<<1|1,mid+1,r,L,R,x);
pushUp(rt);
}
} inline LL query(int rt,int l,int r,int L,int R)
{
if(L<=l&&r<=R) return tr[rt];
pushDown(rt,l,r);
LL res=0;
if(L<=mid) res+=query(rt<<1,l,mid,L,R);
if(R>mid) res+=query(rt<<1|1,mid+1,r,L,R);
return res;
} int main()
{
int n;
while(scanf("%d",&n)&&n)
{
for(int i=1;i<=n;++i) scanf("%d",a+i);
getMex(n);
build(1,1,n);
LL ans=query(1,1,n,1,n);
for(int i=1;i<n;++i){
int p=query_up(1,1,n,i+1,nxt[i]-1,a[i]);
if(p>0) update(1,1,n,p,nxt[i]-1,a[i]);
ans+=query(1,1,n,i+1,n);
}
printf("%lld\n",ans);
}
return 0;
}

  

HDU-4747 Mex(线段树区间更新)的更多相关文章

  1. hdu 4031 attack 线段树区间更新

    Attack Time Limit: 5000/3000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others)Total Subm ...

  2. hdu 4747 mex 线段树+思维

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

  3. HDU 5861 Road 线段树区间更新单点查询

    题目链接: http://acm.split.hdu.edu.cn/showproblem.php?pid=5861 Road Time Limit: 12000/6000 MS (Java/Othe ...

  4. HDU 3308 LCIS 线段树区间更新

    最近开始线段树一段时间了,也发现了不少大牛的博客比如HH大牛  ,小媛姐.这个题目是我在看HH大牛的线段树专题是给出的习题,(可以去他博客找找,真心推荐)原本例题是POJ3667 Hotel 这个题目 ...

  5. hdu 1698(线段树区间更新)

    Just a Hook Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  6. hdu 4747 Mex( 线段树? 不,区间处理就行(dp?))

    Mex Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)Total Submis ...

  7. HDU 1556【线段树区间更新】

    这篇lazy讲的很棒: https://www.douban.com/note/273509745/ if(tree[rt].l == l && r == tree[rt].r) 这里 ...

  8. HDU 4747 Mex ( 线段树好题 + 思路 )

    参考:http://www.cnblogs.com/oyking/p/3323306.html 相当不错的思路,膜拜之~ 个人理解改日补充. #include <cstdio> #incl ...

  9. HDU 5023 A Corrupt Mayor's Performance Art(线段树区间更新)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5023 解题报告:一面墙长度为n,有N个单元,每个单元编号从1到n,墙的初始的颜色是2,一共有30种颜色 ...

  10. HDU 4902 Nice boat 2014杭电多校训练赛第四场F题(线段树区间更新)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4902 解题报告:输入一个序列,然后有q次操作,操作有两种,第一种是把区间 (l,r) 变成x,第二种是 ...

随机推荐

  1. PowerShell工具脚本---按行数切割大文本文件

    我编写的PowerShell工具脚本,[按行数切割大(文本)文件],生成n个小文件. 主要目的是为了能够让excel快速处理.或用脚本并发处理文本. 注意: 1 如果有必要,你可以先用其他工具,把大文 ...

  2. iOS 引导页组件 HcdGuideView

    HcdGuideView HcdGuideView让你为你的app添加一个漂亮的启动页变得简单. 要求 Xcode 6 or higher iOS 7.0 or higher ARC 安装方法 手动安 ...

  3. 匹配IP地址的正则表达式 (转)

    正则表达式 ^(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[ ...

  4. Ogre中Mesh的加载过程详述

    转自:http://blog.csdn.net/yanonsoftware/article/details/1031891 如果新开始写一个3D渲染引擎,Mesh应该是一个很好的切入点.当一个看似简单 ...

  5. windows程序设计笔记

    2014.05.06 新建一个visual C++ -- 常规 -- 空白 的项目,用.c后缀名指定这是一个用C语言来写的windows项目.和C语言的hellworld程序做了一个比较,按照wind ...

  6. 爬虫学习--使用百度api---天气

    #coding:utf-8#version:0.1#note:该即用API能查询指定城市的空气质量指数,但城市数量有限,截止2015年3月26日,只能查到全国161个城市的. import urlli ...

  7. Android 线程模型

    Android 线程模型 1. import android.os.Handler;  import android.os.Message; public class MainActivity ext ...

  8. codeforces 711C Coloring Trees(DP)

    题目链接:http://codeforces.com/problemset/problem/711/C O(n^4)的复杂度,以为会超时的 思路:dp[i][j][k]表示第i棵数用颜色k涂完后bea ...

  9. 微信公众平台 验证URL及简单设置

    加密/校验流程如下: 1. 将token.timestamp.nonce三个参数进行字典序排序 2. 将三个参数字符串拼接成一个字符串进行sha1加密 3. 开发者获得加密后的字符串可与signatu ...

  10. 20135214万子惠 (2)——-Java面向对象程序设计

    实验内容 1. 初步掌握单元测试和TDD 2. 理解并掌握面向对象三要素:封装.继承.多态 3. 初步掌握UML建模 4. 熟悉S.O.L.I.D原则 5. 了解设计模式 (一)单元测试 (1) 三种 ...