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>雾雨魔理 ...
随机推荐
- 图论算法->最短路
求最短路算法,有Floyd,dijkstra,Bellmanford,spfa等诸多高级算法.优化方法也是层出不穷. 我们不妨分析一下各算法的使用特点(可能不准确 1.Floyd算法 复杂度O(n³) ...
- Poj 3189 Steady Cow Assignment (多重匹配)
题目链接: Poj 3189 Steady Cow Assignment 题目描述: 有n头奶牛,m个棚,每个奶牛对每个棚都有一个喜爱程度.当然啦,棚子也是有脾气的,并不是奶牛想住进来就住进来,超出棚 ...
- Ignatius and the Princess III HDU - 1028 || 整数拆分,母函数
Ignatius and the Princess III HDU - 1028 整数划分问题 假的dp(复杂度不对) #include<cstdio> #include<cstri ...
- Styles and Themens(4)android自定义主题时可使用的属性
A list of the standard attributes that you can use in themes can be found at R.styleable.Theme. Cons ...
- java基础(六):RabbitMQ 入门
建议先了解为什么项目要使用 MQ 消息队列,MQ 消息队列有什么优点,如果在业务逻辑上没有此种需求,建议不要使用中间件.中间件对系统的性能做优化的同时,同时增加了系统的复杂性也维护难易度:其次,需要了 ...
- LN : leetcode 123 Best Time to Buy and Sell Stock III
lc 123 Best Time to Buy and Sell Stock III 123 Best Time to Buy and Sell Stock III Say you have an a ...
- 2017广东工业大学程序设计竞赛决赛 G 等凹数字
题意: Description 定义一种数字称为等凹数字,即从高位到地位,每一位的数字先非递增再非递减,不能全部数字一样,且该数是一个回文数,即从左读到右与从右读到左是一样的,仅形成一个等凹峰,如54 ...
- sql发送邮件- html 格式
ALTER PROCEDURE dbo.sx_pro_AutoEmailContent AS Begin declare @Rqty int declare @n int declare @m_rec ...
- 语音行业技术领先者Nuance上海诚招ASR/NLP研发工程师和软件工程师
Nuance is a leading provider of voice and language solutions for businesses and consumers around the ...
- 数据库系统概论(1)——Chap. 1 Introduction
数据库系统概论--Introduction 一.数据库的4个基本概念 数据(data):数据是数据库中存储的基本单位.我们把描述事物的符号记录称为数据.数据和关于数据的解释是不可分的,数据的含义称为数 ...