题目大意:给一个长度为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. 解决VS2010控制台程序运行结束不显示请按任意键继续

    在VS2010里的控制台应用程序在运行时,结果画面一闪而过,不管是用F5 还是用Ctrl + F5都是一样,导致无法看到结果. 网上有不少的办法,说是都是在程序最后加一个要程序暂停的语句( syste ...

  2. Processon 一款基于HTML5的在线作图工具

    CSDN的蒋涛不久前在微博上评价说ProcessOn是web版的visio,出于好奇私下对ProcessOn进行了一番研究.最后发现无论是在用户体验上,还是在技术上,ProcessOn都比微软的Vis ...

  3. [处理器、单片机]ARM

    1.ARM简介: ARM是Advanced RISC Machines的缩写.1985年4月26日,第一个ARM原型在英国剑桥的Acorn计算机有限公司诞生,由美国加州San Jose VLSI技术公 ...

  4. JS内置对象

    字符串对象 <script> //字符串对象 var str = "Hello worldlsgjlsjg"; document.write('string.lengt ...

  5. PHP里10个鲜为人知但却非常有用的函数

    levenshtein() 你有没有经历过需要知道两个单词有多大的不同的时候,这个函数就是来帮你解决这个问题的.它能比较出两个字符串的不同程度. 用法: <?php $str1 = " ...

  6. 《CheckboxDemo.java》

    import java.awt.*; import java.applet.Applet; public class CheckboxDemo extends Applet { String Uni[ ...

  7. unity3d基础01

    Unity3d 五大视图: 1 Scene:存放hierarchy中创建的游戏对象,但实际只能看到一部分 *Scene浏览: ①右键进入“飞行模式”,方便查看整个场景 ②选中摄像机,按ALT进入浏览的 ...

  8. hdu 2036

    Ps:  - -感觉这道题完全就是数学题...就是求知道每个顶点的坐标,然后求这个多边形的面积... 代码:#include "stdio.h"#include "std ...

  9. 2016 - 1 - 21 RunloopMode中的Source 与Observer

    一:CFRunLoopSourceRef 1.CFRunLoopSourceRef是事件源(输入源) 2.按照官网文档分为,Source可以分为以下几类: 2.1 Porl - Based Sourc ...

  10. 集合set的使用

    将无序对象储存在集合中 集合是类似于数组的一组对象,只是其中包含的项目是无序的(而数组是有序的).您通过枚举集合中的对象,或者将过滤器或测试应用到集合,来随机访问集合中的对象(使用 anyObject ...