hdu 4747 Mex
http://acm.hdu.edu.cn/showproblem.php?pid=4747
设我们输入的数组为 a[],我们需要从 1 到 n 遍历, 假设遍历到 i 时, 遍历的过程中用b[j]表示从 i 到 j 没出现的最小自然数
先从 n 到 1 扫一遍求出从 1 到各个点的b[j]值
然后遍历a[] 实际上就是不断的把当前a[i] 去掉,比如说去掉a[3]时,剩下的b[4]---b[n] 就表示从4到其他后续点形成的区间中没出现的最小自然数
要知道从 i 到 n ,b[]的值始终是单调递增的
我们每去掉当前a[i]会对b[]数组产生影响,
设下一个和a[i]相等的数出现的位置是 r 那么去掉a[i] 对 r 以及 r 以后的b[] 没有影响
在 i 和 r 之间受影响的段b[]是大于等于a[i]的那一段 假设是(l,r), 这个段内的b[]都大于等于a[i]
去掉a[i]的影响就是这个段内的b[] 都要等于 a[i]
找到r可以事先标记,找 l 和更新段 (l,r) 有两种方法
1,二分找到 l ,然后遍历更新段 (l,r) 这样代码比较短,也比较易懂,但比较耗时,不过可以过
2,线段树维护 这样代码量会比较大,不过耗时少,线段树的解法应该比较标准
两种代码:
- #include<iostream>
- #include<cstdio>
- #include<algorithm>
- #include<string>
- #include<cstring>
- #include<cmath>
- #include<set>
- #include<vector>
- #include<list>
- #include<stack>
- #include<queue>
- #include<map>
- using namespace std;
- typedef long long ll;
- typedef pair<int,int> pp;
- const int INF=0x3f3f3f3f;
- const int N=200002;
- bool exist[N];
- int a[N],next[N],f[N];
- int b[N];
- int bsh(int l,int r,int k)
- {
- while(l<=r)
- {
- int mid=(l+r)>>1;
- if(b[mid]<=k) l=mid+1;
- else r=mid-1;
- }
- return r;
- }
- int main()
- {
- //freopen("data.in","r",stdin);
- int n;
- while(scanf("%d",&n)!=EOF)
- {
- if(n==0) break;
- for(int i=1;i<=n;++i)
- scanf("%d",&a[i]);
- for(int i=0;i<=n;++i)
- f[i]=n+1;
- for(int i=n;i>=1;--i)
- if(a[i]<n)
- {
- next[i]=f[a[i]];
- f[a[i]]=i;
- }
- ll ans=0;
- memset(exist,false,sizeof(exist));
- ll tmp=0;int l=0;
- for(int i=1;i<=n;++i)
- {
- if(a[i]<n)
- {
- exist[a[i]]=true;
- while(exist[l]) ++l;
- }
- b[i]=l;
- tmp+=b[i];
- }
- ans=tmp;
- for(int i=1;i<n;++i)
- {
- if(a[i]<n)
- {
- int r=next[i];
- int l=bsh(i,r-1,a[i]);
- for(int j=l+1;j<r;++j)
- {
- tmp-=(b[j]-a[i]);
- b[j]=a[i];
- }
- }
- tmp-=b[i];
- ans+=tmp;
- }
- cout<<ans<<endl;
- }
- return 0;
- }
- #include<iostream>
- #include<cstdio>
- #include<algorithm>
- #include<string>
- #include<cstring>
- #include<cmath>
- #include<set>
- #include<vector>
- #include<list>
- #include<stack>
- #include<queue>
- #include<map>
- using namespace std;
- typedef long long ll;
- typedef pair<int,int> pp;
- const int INF=0x3f3f3f3f;
- const int N=200002;
- bool exist[N];
- int a[N],next[N],f[N];
- int b[N];
- struct node
- {
- int l,r,k,least;
- ll sum;
- }tr[N*4];
- void build(int x,int l,int r)
- {
- tr[x].l=l;tr[x].r=r;tr[x].k=-1;
- if(l==r)
- {
- tr[x].least=b[l];
- tr[x].sum=b[l];
- return ;
- }
- int mid=(l+r)>>1;
- build((x<<1),l,mid);
- build((x<<1)|1,mid+1,r);
- tr[x].least=min(tr[x<<1].least,tr[(x<<1)|1].least);
- tr[x].sum=(tr[x<<1].sum+tr[(x<<1)|1].sum);
- }
- void update(int x,int l,int r,int k)
- {
- if(l>r) return ;
- if(tr[x].l==l&&tr[x].r==r)
- {
- tr[x].least=k;
- tr[x].k=k;
- tr[x].sum=(ll)k*(tr[x].r-tr[x].l+1);
- return ;
- }
- if(tr[x].k!=-1)
- {
- tr[x<<1].k=tr[x].k;tr[x<<1].least=tr[x<<1].k;
- tr[x<<1].sum=(ll)tr[x<<1].k*(tr[x<<1].r-tr[x<<1].l+1);
- tr[(x<<1)|1].k=tr[x].k;tr[(x<<1)|1].least=tr[(x<<1)|1].k;
- tr[(x<<1)|1].sum=(ll)tr[(x<<1)|1].k*(tr[(x<<1)|1].r-tr[(x<<1)|1].l+1);
- tr[x].k=-1;
- }
- int mid=(tr[x].l+tr[x].r)>>1;
- if(r<=mid)
- update(x<<1,l,r,k);
- else if(l>mid)
- update((x<<1)|1,l,r,k);
- else
- {
- update(x<<1,l,mid,k);
- update((x<<1)|1,mid+1,r,k);
- }
- tr[x].least=min(tr[x<<1].least,tr[(x<<1)|1].least);
- tr[x].sum=(tr[x<<1].sum+tr[(x<<1)|1].sum);
- tr[x].k=-1;
- }
- int get(int x,int l,int r,int w)
- {
- if(tr[x].l==tr[x].r)
- {
- if(tr[x].least>w)
- return (l-1);
- return l;
- }
- if(tr[x].k!=-1)
- {
- tr[x<<1].k=tr[x].k;tr[x<<1].least=tr[x<<1].k;
- tr[x<<1].sum=(ll)tr[x<<1].k*(tr[x<<1].r-tr[x<<1].l+1);
- tr[(x<<1)|1].k=tr[x].k;tr[(x<<1)|1].least=tr[(x<<1)|1].k;
- tr[(x<<1)|1].sum=(ll)tr[(x<<1)|1].k*(tr[(x<<1)|1].r-tr[(x<<1)|1].l+1);
- tr[x].k=-1;
- }
- int mid=(tr[x].l+tr[x].r)>>1;
- if(r<=mid)
- return get(x<<1,l,r,w);
- else if(l>mid)
- return get((x<<1)|1,l,r,w);
- else
- {
- if(tr[(x<<1)|1].least<=w)
- return get((x<<1)|1,mid+1,r,w);
- else
- return get(x<<1,l,mid,w);
- }
- }
- ll gsum(int x,int l,int r)
- {
- if(l>r) return 0;
- if(tr[x].l==l&&tr[x].r==r)
- return tr[x].sum;
- if(tr[x].k!=-1)
- {
- tr[x<<1].k=tr[x].k;tr[x<<1].least=tr[x<<1].k;
- tr[x<<1].sum=(ll)tr[x<<1].k*(tr[x<<1].r-tr[x<<1].l+1);
- tr[(x<<1)|1].k=tr[x].k;tr[(x<<1)|1].least=tr[(x<<1)|1].k;
- tr[(x<<1)|1].sum=(ll)tr[(x<<1)|1].k*(tr[(x<<1)|1].r-tr[(x<<1)|1].l+1);
- tr[x].k=-1;
- }
- int mid=(tr[x].l+tr[x].r)>>1;
- if(r<=mid)
- return gsum(x<<1,l,r);
- else if(l>mid)
- return gsum((x<<1)|1,l,r);
- else
- return gsum(x<<1,l,mid)+gsum((x<<1)|1,mid+1,r);
- }
- int main()
- {
- int n;
- while(scanf("%d",&n)!=EOF)
- {
- if(n==0) break;
- for(int i=1;i<=n;++i)
- scanf("%d",&a[i]);
- for(int i=0;i<=n;++i)
- f[i]=n+1;
- for(int i=n;i>=1;--i)
- if(a[i]<n)
- {
- next[i]=f[a[i]];
- f[a[i]]=i;
- }
- ll ans=0;
- memset(exist,false,sizeof(exist));
- int l=0;
- for(int i=1;i<=n;++i)
- {
- if(a[i]<n)
- {
- exist[a[i]]=true;
- while(exist[l]) ++l;
- }
- b[i]=l;
- }
- build(1,1,n);
- ans+=gsum(1,1,n);
- for(int i=1;i<n;++i)
- {
- if(a[i]<n)
- {
- int r=next[i];
- int l=get(1,i,r-1,a[i]);
- update(1,l+1,r-1,a[i]);
- }
- ans+=gsum(1,i+1,n);
- }
- cout<<ans<<endl;
- }
- return 0;
- }
hdu 4747 Mex的更多相关文章
- HDU 4747 Mex 递推/线段树
题目链接: acm.hdu.edu.cn/showproblem.php?pid=4747 Mex Time Limit: 15000/5000 MS (Java/Others)Memory Limi ...
- 【HDU 4747 Mex】线段数
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4747 题意:有一组序列a[i](1<=i<=N), 让你求所有的mex(l,r), mex ...
- [HDU 4747] Mex (线段树)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4747 这道题是我去年刚入校队的时候参加网赛的题目. 一年过去了,我依然还是不会做.. 这是我难题计划的 ...
- HDU 4747 Mex(线段树)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4747 题意:给出一个数列A.计算所有的mex(i,j)之和.1<=i<=j<=n. ...
- hdu 4747 Mex (2013 ACM/ICPC Asia Regional Hangzhou Online)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4747 思路: 比赛打得太菜了,不想写....线段树莽一下 实现代码: #include<iost ...
- hdu 4747 mex 线段树+思维
http://acm.hdu.edu.cn/showproblem.php?pid=4747 题意: 我们定义mex(l,r)表示一个序列a[l]....a[r]中没有出现过得最小的非负整数, 然后我 ...
- HDU 4747 Mex (2013杭州网络赛1010题,线段树)
Mex Time Limit: 15000/5000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)Total Submis ...
- hdu 4747 Mex( 线段树? 不,区间处理就行(dp?))
Mex Time Limit: 15000/5000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)Total Submis ...
- 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 ...
随机推荐
- 安装第三方库出现 Python version 2.7 required, which was not found in the registry
安装第三方库出现 Python version 2.7 required, which was not found in the registry 建立一个文件 register.py 内容如下. 然 ...
- jQuery表单验证插件——jquery.validate.js
官网地址:http://bassistance.de/jquery-plugins/jquery-plugin-validation 一.导入js库 <script src="../j ...
- static const vs. extern const
在实现文件(.m文件)中使用static const来定义“只在编译单元内可见的常量”(只在.m文件内可见),由于此类常量不在全局符号表中,所以无须为其名称加类名前缀(一般以k开头). 在头文件中使用 ...
- c#下载网页源码的两种方法
1.WebClient: System.Net.WebClient wc = new System.Net.WebClient(); Byte[] pageData = wc.DownloadData ...
- android录像增加时间记录(源码里修改)
需要做一个功能,录像和播放时都显示录时的时间,参考文章链接找不到了,不好意思,这里记录一下,防止下次找不到了.另一篇关于源码录像的流程请参考 http://www.verydemo.com/demo_ ...
- Burning Bridges-ZOJ1588(割边求解)
Burning Bridges Time Limit: 5 Seconds Memory Limit: 32768 KB Ferry Kingdom is a nice little country ...
- python 学习笔记十一 SQLALchemy ORM(进阶篇)
SqlAlchemy ORM SQLAlchemy是Python编程语言下的一款ORM框架,该框架建立在数据库API之上,使用关系对象映射进行数据库操作,简言之便是:将对象转换成SQL,然后使用数据A ...
- R----lubridata包介绍学习
lubridate包,非常强大,能够识别各种类型的日期.字符型和时间型数据,都是格式比较特别的你数据,在处理时,比较麻烦,但是有了lubridate这个包之后,时间处理变得非常简单,这个包函数命名简单 ...
- 【转】CentOS下载版本介绍
官网:http://www.centos.org/ 下载:http://mirror.neu.edu.cn/centos/6.6/isos/ 系统运维:http://www.osyunwei.com/ ...
- Hibernate不能自动建数据表解决办法
首先自己要注意自己的MYSQL版本,然后设置对应的方言 兼容性模式 <property name="hibernate.dialect">org.hibernate.d ...