题目链接: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. 【转】Linux IO实时监控iostat命令详解

    转自:http://www.cnblogs.com/ggjucheng/archive/2013/01/13/2858810.html 简介 iostat主要用于监控系统设备的IO负载情况,iosta ...

  2. 启动hbase时出现HMaster Aborted错误

    启动hbase时出现 java.lang.RuntimeException: HMaster Aborted at org.apache.hadoop.hbase.master.HMasterComm ...

  3. HDU 5867 Sparse Graph (2016年大连网络赛 I bfs+补图)

    题意:给你n个点m条边形成一个无向图,问你求出给定点在此图的补图上到每个点距离的最小值,每条边距离为1 补图:完全图减去原图 完全图:每两个点都相连的图 其实就是一个有技巧的bfs,我们可以看到虽然点 ...

  4. Liferay 6.2 改造系列之二十三:修改Liferay原始主题中"技术支持:Liferay"字样

    1.修改主题模板文件,具体位置如下 (1) portal-master\portal-web\docroot\html\themes\_unstyled\templates\portal_normal ...

  5. 在caffe中添加新的layer

    比如现在要添加一个vision layer,名字叫Ly_Layer:(一般命名第一个字母大写,其余小写.) 1.属于哪个类型的layer(共五种:common_layer, data_layer, l ...

  6. XSS 跨站脚本攻击之构造剖析(一)

    1.XSS-Filter:跨站脚本过滤器,用于分析用户提交的输入,并消除潜在的跨站脚本攻击 (1)XSS Filter实际上是一段精心编写的过滤函数作用是过滤XSS跨站脚本代码: (2)绕过XSS F ...

  7. js整理1

    数组 比较时的隐式转化 var a = [1,2,3]; var b = [1,2,3]; a == b; //false a == '1,2,3'; //true; // var c = []; B ...

  8. virtual方法和abstract方法

    在C#的学习中,容易混淆virtual方法和abstract方法的使用,现在来讨论一下二者的区别.二者都牵涉到在派生类中与override的配合使用. 一.Virtual方法(虚方法) virtual ...

  9. html中frameset的详细使用方法

    http://blog.csdn.net/csb5201314/article/details/5695417

  10. ReSharper 配置及用法(二)

    下载工具 一:Reshaper是什么 即便是那些整天攻击 .NET 和 C# 的人,也常常不得不承认 Visual Studio 确实是个够强大的 IDE,除非他认为更少的 IDE 功能和命令行调试才 ...