题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4747

题意:有一组序列a[i](1<=i<=N), 让你求所有的mex(l,r), mex(l,r)表示区间[l,r]中最小的未在序列中出现的非负整数。

思路:冥思苦想半天无想法,白做了那么多线段树。 很明显的维护区间问题,容易想到线段树,比较难想到操作。 枚举一个序列的所mex(1,i),mex(2,i)……可以发现序列mex(x,i)是一个单调递增序列,我们需要求得就是所有以x开头的序列和,mex(x,i)(x<=i<=n)。这点确定了就好办了,记录每个位置的数后面最早重复出现的位置next[x],如果无则为设n+1。那么我们就可以发现,当第x个数所对应的序列 mex(x,i)(x<=i<=n)所对应的序列求完之后,删去此位置的数,位置x+1~next[x]-1序列中mex值大于a[x]的都改为a[x],因为a[x]没有了,下一个a[x]还未出现,所以可以证明这样做是正确的。从1到n扫一遍亦求出了所有的mex()。

基本上所有的操作都可以用到线段树。开始没有想到一点的是如何找序列中刚好大于a[x]的位置,并且此位置到next[x]-1赋值为a[x],怎么都没想到log(n)的操作,其实这里依然可以用到线段树,因为序列是单调递增的,另开一个区间维护序列mavv[u]表示区间中最大的mex值,随着询问以及其他操作成段更新即可。

 #include <iostream>
#include <cstdio>
#include <cmath>
#include <map>
#include <algorithm>
#include <cstring>
#include <sstream>
using namespace std; #define lz 2*u,l,mid
#define rz 2*u+1,mid+1,r
typedef long long lld;
const int maxn=;
int a[maxn], b[maxn], next[maxn];
lld sum[*maxn], mavv[*maxn], flag[*maxn];
map<int,int>mp; void push_up(int u, int l, int r)
{
sum[u]=sum[*u]+sum[*u+];
mavv[u]=mavv[*u+];
} void push_down(int u, int l, int r)
{
int mid=(l+r)>>;
if(flag[u]!=-)
{
flag[*u]=flag[*u+]=flag[u];
mavv[*u]=mavv[*u+]=flag[u];
sum[*u]=(lld)(mid-l+)*flag[u];
sum[*u+]=(lld)(r-mid)*flag[u];
flag[u]=-;
}
} void build(int u, int l, int r)
{
flag[u]=-;
int mid=(l+r)>>;
if(l==r)
{
sum[u]=mavv[u]=b[l];
return ;
}
build(lz);
build(rz);
push_up(u,l,r);
} void Update(int u, int l, int r, int tl, int tr, int val)
{
if(tl>tr) return ;
if(tl<=l&&r<=tr)
{
mavv[u]=val;
sum[u]=(lld)val*(r-l+);
flag[u]=val;
return ;
}
push_down(u,l,r);
int mid=(l+r)>>;
if(tr<=mid) Update(lz,tl,tr,val);
else if(tl>mid) Update(rz,tl,tr,val);
else
{
Update(lz,tl,mid,val);
Update(rz,mid+,tr,val);
}
push_up(u,l,r);
} int find(int u, int l, int r, int tmp)
{
if(l==r) return l;
push_down(u,l,r);
int mid=(l+r)>>;
if(mavv[*u]>tmp) return find(lz,tmp);
else return find(rz,tmp);
} int main()
{
int n;
while(cin >> n,n)
{
for(int i=; i<=n; i++) scanf("%d",a+i);
mp.clear();
for(int i=n; i>=; i--)
{
if(mp[ a[i] ]) next[i]=mp[ a[i] ];
else next[i]=n+;
mp[ a[i] ]=i;
}
mp.clear();
int x=;
for(int i=; i<=n; i++)
{
mp[ a[i] ]=;
while(mp[x]) ++x;
b[i]=x;
}
build(,,n);
lld ans=;
for(int i=; i<=n; i++)
{
ans+=sum[];
if(mavv[]>a[i])
{
int id=find(,,n,a[i]);
Update(,,n,max(id,i+),next[i]-,a[i]);
}
Update(,,n,i,i,);
}
cout << ans <<endl;
}
}

【HDU 4747 Mex】线段数的更多相关文章

  1. hdu 4747 mex 线段树+思维

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

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

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

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

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

  4. HDU 4747 Mex 递推/线段树

    题目链接: acm.hdu.edu.cn/showproblem.php?pid=4747 Mex Time Limit: 15000/5000 MS (Java/Others)Memory Limi ...

  5. HDU 4747 Mex(线段树)(2013 ACM/ICPC Asia Regional Hangzhou Online)

    Problem Description Mex is a function on a set of integers, which is universally used for impartial ...

  6. [HDU 4747] Mex (线段树)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4747 这道题是我去年刚入校队的时候参加网赛的题目. 一年过去了,我依然还是不会做.. 这是我难题计划的 ...

  7. HDU 4747 Mex(线段树)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4747 题意:给出一个数列A.计算所有的mex(i,j)之和.1<=i<=j<=n. ...

  8. HDU 4747 Mex (2013杭州网络赛1010题,线段树)

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

  9. HDU 4747 Mex【线段树上二分+扫描线】

    [题意概述] 一个区间的Mex为这个区间没有出现过的最小自然数,现在给你一个序列,要求求出所有区间的Mex的和. [题解] 扫描线+线段树. 我们在线段树上维护从当前左端点开始的前缀Mex,显然从左到 ...

随机推荐

  1. 自己yy的fulkson最大流算法

    #include <iostream> #include <cstdio> #include <vector> using namespace std; ; //m ...

  2. OGNL表示式使用和值栈

    另外值得参考博客:http://blog.csdn.net/resigshy/article/details/7560573 OGNL是Object Graphic Navigation Langua ...

  3. 【转】Kylin中的cube构建

    http://blog.csdn.net/yu616568/article/details/50365240 前言   在使用Kylin的时候,最重要的一步就是创建cube的模型定义,即指定度量和维度 ...

  4. AOP静态代理解析1-标签解析

    AOP静态代理使用示例见Spring的LoadTimeWeaver(代码织入) Instrumentation使用示例见java.lang.instrument使用 AOP的静态代理主要是在虚拟机启动 ...

  5. hdu1087 最大递增子段和

    http://acm.split.hdu.edu.cn/showproblem.php?pid=1087 状态方程:sum[j]=max{sum[i]}+a[j]; 其中,0<=i<=j, ...

  6. python 线程之_thread

    python 线程之_thread _thread module: 基本用法: def child(tid): print("hello from child",tid) _thr ...

  7. mongodb 连接和操作

    使用方法: 1.安装mongodb 2.配置环境变量 mac下: export PATH=/Users/sunbey/Documents/learn/mongodb/mongodb-osx-x86_6 ...

  8. json时间格式化问题

    function jsonDateFormat(jsonDate) {//json日期格式转换为正常格式 try { var date = new Date(parseInt(jsonDate.rep ...

  9. ural 1143. Electric Path

    1143. Electric Path Time limit: 1.0 secondMemory limit: 64 MB Background At the team competition of ...

  10. CF# Educational Codeforces Round 3 B. The Best Gift

    B. The Best Gift time limit per test 2 seconds memory limit per test 256 megabytes input standard in ...