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

【题意概述】
一个区间的Mex为这个区间没有出现过的最小自然数,现在给你一个序列,要求求出所有区间的Mex的和。
【题解】
扫描线+线段树。
我们在线段树上维护从当前左端点开始的前缀Mex,显然从左到右Mex单调上升。
然后我们把区间左端点逐渐向右边移动,也就是扫描线是左端点。
我们可以发现每次移动的影响就是 [这个数的位置, 这个数下一次出现的位置) 这个区间内大于这个数的Mex全部变为这个数。
那么我们在线段树上二分出第一个大于等于Mex的位置,然后区间修改即可。
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
#define rg register
#define N 200010
#define ls (u<<1)
#define rs (u<<1|1)
#define mid ((a[u].l+a[u].r)>>1)
using namespace std;
int n,m,v[N],b[N],c[N],nxt[N],pos[N],mex[N];
LL ans,u[N];
struct tree{int l,r,nl,nr; LL sum; bool tag;}a[N<<];
inline int read(){
int k=,f=; char c=getchar();
while(c<''||c>'')c=='-'&&(f=-),c=getchar();
while(''<=c&&c<='')k=k*+c-'',c=getchar();
return k*f;
}
void build(int u,int l,int r){
a[u].l=l; a[u].r=r; a[u].tag=;
if(l<r){
build(ls,l,mid); build(rs,mid+,r);
a[u].sum=a[ls].sum+a[rs].sum; a[u].nl=a[ls].nl,a[u].nr=a[rs].nr;
}
else a[u].sum=a[u].nl=a[u].nr=mex[l];
}
inline void pushdown(int u){
a[ls].tag=a[rs].tag=;
a[ls].nl=a[ls].nr=a[rs].nl=a[rs].nr=a[u].nl;
a[ls].sum=(a[ls].r-a[ls].l+)*a[ls].nl;
a[rs].sum=(a[rs].r-a[rs].l+)*a[rs].nl;
a[u].tag=;
}
void update(int u,int l,int r,int num){
if(l<=a[u].l&&a[u].r<=r&&a[u].nl>num){
a[u].tag=; a[u].nl=a[u].nr=num; a[u].sum=(a[u].r-a[u].l+)*num;
return;
}
if(a[u].nr<=num) return;
if(a[u].tag) pushdown(u);
if(a[ls].nr>num&&l<=mid) update(ls,l,r,num);
if(r>mid) update(rs,l,r,num);
a[u].sum=a[ls].sum+a[rs].sum; a[u].nl=a[ls].nl,a[u].nr=a[rs].nr;
}
LL query(int u,int l,int r){
if(l<=a[u].l&&a[u].r<=r) return a[u].sum;
if(a[u].tag) pushdown(u); LL ret=;
if(l<=mid) ret+=query(ls,l,r);
if(r>mid) ret+=query(rs,l,r);
return ret;
}
inline void Pre(){
ans=;
memset(pos,,sizeof(pos));
memset(u,,sizeof(u));
}
int main(){
while(){
n=read(); if(!n) break;
Pre();
for(rg int i=;i<=n;i++) v[i]=b[i]=read();
sort(b+,b++n); m=unique(b+,b++n)-b-;
for(rg int i=;i<=n;i++) c[i]=lower_bound(b+,b++m,v[i])-b;
// for(rg int i=1;i<=n;i++) printf("%d ",c[i]); puts("c");
for(rg int i=n;i;i--) nxt[i]=(pos[c[i]])?pos[c[i]]:n+,pos[c[i]]=i;
// for(rg int i=1;i<=n;i++) printf("%d ",nxt[i]); puts("");
int now=;
for(rg int i=;i<=n;i++){
if(v[i]<=n) u[v[i]]=;
while(u[now]) now++;
ans+=(mex[i]=now);
}
// for(rg int i=1;i<=n;i++) printf("%d ",mex[i]);
// printf("ans=%lld\n",ans);
build(,,n);
for(rg int i=;i<=n;i++){
update(,i+,nxt[i]-,v[i]);
ans+=query(,i+,n);
// printf("ans=%lld\n",ans);
}
printf("%lld\n",ans);
}
return ;
}
HDU 4747 Mex【线段树上二分+扫描线】的更多相关文章
- hdu 5930 GCD 线段树上二分/ 强行合并维护信息
from NOIP2016模拟题28 题目大意 n个点的序列,权值\(<=10^6\) q个操作 1.单点修改 2.求所有区间gcd中,不同数个数 分析 1.以一个点为端点,向左或向右的gcd种 ...
- hdu 4747 mex 线段树+思维
http://acm.hdu.edu.cn/showproblem.php?pid=4747 题意: 我们定义mex(l,r)表示一个序列a[l]....a[r]中没有出现过得最小的非负整数, 然后我 ...
- hdu 4747 Mex( 线段树? 不,区间处理就行(dp?))
Mex Time Limit: 15000/5000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)Total Submis ...
- HDU 4747 Mex ( 线段树好题 + 思路 )
参考:http://www.cnblogs.com/oyking/p/3323306.html 相当不错的思路,膜拜之~ 个人理解改日补充. #include <cstdio> #incl ...
- HDU 4747 Mex 递推/线段树
题目链接: acm.hdu.edu.cn/showproblem.php?pid=4747 Mex Time Limit: 15000/5000 MS (Java/Others)Memory Limi ...
- LOJ 3059 「HNOI2019」序列——贪心与前后缀的思路+线段树上二分
题目:https://loj.ac/problem/3059 一段 A 选一个 B 的话, B 是这段 A 的平均值.因为 \( \sum (A_i-B)^2 = \sum A_i^2 - 2*B \ ...
- 贪心+离散化+线段树上二分。。。 Samara University ACM ICPC 2016-2017 Quarterfinal Qualification Contest G. Of Zorcs and Axes
题目链接:http://codeforces.com/gym/101149/problem/G 题目大意:给你n对数字,为(a[i], b[i]),给你m对数字,为(w[i], c[i]).给n对数字 ...
- 【BZOJ】4293: [PA2015]Siano 线段树上二分
[题意]给定n棵高度初始为0的草,每天每棵草会长高a[i],m次收割,每次在d[i]天将所有>b[i]的草收割到b[i],求每次收割量.n<=500000. [算法]线段树上二分 [题解] ...
- [NOIP2015模拟10.27] [JZOJ4270] 魔道研究 解题报告(动态开点+权值线段树上二分)
Description “我希望能使用更多的魔法.不对,是预定能使用啦.最终我要被大家称呼为大魔法使.为此我决定不惜一切努力.”——<The Grimoire of Marisa>雾雨魔理 ...
随机推荐
- 2017 ACM-ICPC Asia East Final T1
好弱啊只会T1,在Chemist&&wxh两位dalao的指导下搞懂. 题解如下.[手写版本 滑稽 code #include<bits/stdc++.h> using n ...
- springboot整合elasticsearch出错:java.lang.NoClassDefFoundError: org/elasticsearch/plugins/NetworkPlugin
Caused by: java.lang.NoClassDefFoundError: org/elasticsearch/plugins/NetworkPlugin at java.lang.Clas ...
- 51nod 1138 连续整数的和
1138 连续整数的和 基准时间限制:1 秒 空间限制:131072 KB 分值: 10 难度:2级算法题 收藏 关注 给出一个正整数N,将N写为若干个连续数字和的形式(长度 >= 2). ...
- 洛谷 P2062 分队问题
这题太毒了....一开始就是死活想不到,结果看了很多遍题解,重新做的时候还是做不出来.. 好像有一点被错误的题解误导了? #include<cstdio> #include<algo ...
- Mondriaan's Dream POJ - 2411
Mondriaan's Dream POJ - 2411 可以用状压dp,但是要打一下表.暴力枚举行.这一行的状态.上一行的状态,判断如果上一行的状态能转移到这一行的状态就转移. 状态定义:ans[i ...
- html 测试
斯蒂芬斯蒂芬 20:23你过来吧,我们好好谈一谈 好好学习 21:22这是一个无法避免的错误 作为一个新手,我在学习HTML文件的格式,我觉得博客园的编辑器很棒, 查看这些源代码让我学习到了许多知识. ...
- selenium 延迟等待的三种方式
1.最直接普通的方式:这个是设置固定的等待时间 Thread.sleep(1000); 2.显示等待方式(Explicit Wait):就是明确的要等待的元素在规定的时间之内都没找到,那么就 ...
- [转]为革命保护视力 --- 给 Visual Studio 换颜色
本文转自:http://www.cnblogs.com/stg609/p/3723968.html “为革命,保护视力,预防近视,眼保健操开始......” 这个应该是最老版本的眼保健操了,你听过? ...
- [转]访问 OData 服务 (WCF Data Services)
本文转自:http://msdn.microsoft.com/zh-SG/library/dd728283(v=vs.103) WCF 数据服务 支持开放式数据协议 (OData) 将数据作为包含可通 ...
- 记录一下java在后端用request来判断请求类型
这几天看代码,看到这么一个操作. String requestType = request.getHeader("X-Requested-With"); 于是各种查找 这里记 ...