题目链接:

acm.hdu.edu.cn/showproblem.php?pid=4747

Mex

Time Limit: 15000/5000 MS (Java/Others)
Memory Limit: 65535/65535 K (Java/Others)

问题描述

Mex is a function on a set of integers, which is universally used for impartial game theorem. For a non-negative integer set S, mex(S) is defined as the least non-negative integer which is not appeared in S. Now our problem is about mex function on a sequence.

Consider a sequence of non-negative integers {ai}, we define mex(L,R) as the least non-negative integer which is not appeared in the continuous subsequence from aL to aR, inclusive. Now we want to calculate the sum of mex(L,R) for all 1 <= L <= R <= n.

输入

The input contains at most 20 test cases.

For each test case, the first line contains one integer n, denoting the length of sequence.

The next line contains n non-integers separated by space, denoting the sequence.

(1 <= n <= 200000, 0 <= ai <= 10^9)

The input ends with n = 0.

输出

For each test case, output one line containing a integer denoting the answer.

样例输入

3

0 1 3

5

1 0 2 0 1

0

样例输出

5

24

Hint

For the first test case:

mex(1,1)=1, mex(1,2)=2, mex(1,3)=2, mex(2,2)=0, mex(2,3)=0,mex(3,3)=0.

1 + 2 + 2 + 0 +0 +0 = 5.

题意

mex(s)表示没有在集合s中出现的最小非负数,现在要求所有的mex(si)(si为由数列的一个子串组成的集合)的和。

题解

1、递推、 [参考]

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<ctime>
#include<vector>
#include<cstdio>
#include<string>
#include<bitset>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
using namespace std;
#define X first
#define Y second
#define mkp make_pair
#define lson (o<<1)
#define rson ((o<<1)|1)
#define mid (l+(r-l)/2)
#define sz() size()
#define pb(v) push_back(v)
#define all(o) (o).begin(),(o).end()
#define clr(a,v) memset(a,v,sizeof(a))
#define bug(a) cout<<#a<<" = "<<a<<endl
#define rep(i,a,b) for(int i=a;i<(b);i++)
#define scf scanf
#define prf printf typedef long long LL;
typedef vector<int> VI;
typedef pair<int,int> PII;
typedef vector<pair<int,int> > VPII; const int INF=0x3f3f3f3f;
const LL INFL=0x3f3f3f3f3f3f3f3fLL;
const double eps=1e-8;
const double PI = acos(-1.0); //start---------------------------------------------------------------------- const int maxn=2e5+10; int n;
int arr[maxn];
//last[x]表示x这个数最晚出现的位置
//full[x]表示完全覆盖0到x的且左边界最靠右的区间
int last[maxn],full[maxn];
//dp[i]表示以i结尾的所有区间的贡献
LL dp[maxn]; void init(){
clr(dp,0);
clr(full,0);
clr(last,0);
} int main() {
while(scf("%d",&n)==1&&n){
init();
for(int i=1;i<=n;i++) scf("%d",&arr[i]);
LL ans=0;
for(int i=1;i<=n;i++){
dp[i]=dp[i-1];
if(arr[i]<n){
int v=arr[i];
int pre=last[v];
last[v]=i;
for(int j=v;j<n;j++){
if(j) full[j]=min(last[j],full[j-1]);
else full[j]=i;
if(full[j]>pre) dp[i]+=full[j]-pre;
else break;
}
}
ans+=dp[i];
}
prf("%lld\n",ans);
}
return 0;
} //end-----------------------------------------------------------------------

2、线段树

初始时线段树上第i个节点存mex(a[1]~a[i])(注意!这个存在单调性!)。

然后我们依次从a[1]开始删除,直到删到a[n-1]。 如果删掉a[1],那么我们对于原本mex值就小于等于a[1]的节点自然没有影响,而对于mex>a[1]且其它位置不存在a[1]的元素,删掉这个a[1]之后它的mex值就会等于a[1],所以我们只要用线段树update一下区间[第一个mex值大于a[1](根据单调性在线段树上二分查找)的位置,下一个值等于a[1]的位置-1]。

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<ctime>
#include<vector>
#include<cstdio>
#include<string>
#include<bitset>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
using namespace std;
#define X first
#define Y second
#define mkp make_pair
#define lson (o<<1)
#define rson ((o<<1)|1)
#define mid (l+(r-l)/2)
#define sz() size()
#define pb(v) push_back(v)
#define all(o) (o).begin(),(o).end()
#define clr(a,v) memset(a,v,sizeof(a))
#define bug(a) cout<<#a<<" = "<<a<<endl
#define rep(i,a,b) for(int i=a;i<(b);i++)
#define scf scanf
#define prf printf typedef long long LL;
typedef vector<int> VI;
typedef pair<int,int> PII;
typedef vector<pair<int,int> > VPII; const int INF=0x3f3f3f3f;
const LL INFL=0x3f3f3f3f3f3f3f3fLL;
const double eps=1e-8;
const double PI = acos(-1.0); //start---------------------------------------------------------------------- const int maxn=2e5+10; LL sumv[maxn<<2];
int mexv[maxn<<2],setv[maxn<<2];
int arr[maxn],b[maxn];
bool vis[maxn];
int mp[maxn],last[maxn];
int n; void pushdown(int o,int l,int r) {
if(setv[o]>=0) {
sumv[lson]=(mid-l+1)*setv[o];
mexv[lson]=setv[o]; sumv[rson]=(r-mid)*setv[o];
mexv[rson]=setv[o]; setv[lson]=setv[rson]=setv[o];
setv[o]=-1;
}
} void maintain(int o) {
sumv[o]=sumv[lson]+sumv[rson];
mexv[o]=max(mexv[lson],mexv[rson]);
} void build(int o,int l,int r) {
if(l==r) {
sumv[o]=mexv[o]=b[l];
} else {
build(lson,l,mid);
build(rson,mid+1,r);
maintain(o);
}
} int _v,_pos;
void query(int o,int l,int r) {
if(l==r) {
if(_v>=mexv[o]) _pos=n+1;
else _pos=l;
} else {
pushdown(o,l,r);
if(_v>=mexv[lson]) query(rson,mid+1,r);
else query(lson,l,mid);
maintain(o);
}
} int ql,qr,_v2;
void update(int o,int l,int r) {
if(ql<=l&&r<=qr) {
sumv[o]=(r-l+1)*_v2;
mexv[o]=_v2;
setv[o]=_v2;
} else {
pushdown(o,l,r);
if(ql<=mid) update(lson,l,mid);
if(qr>mid) update(rson,mid+1,r);
maintain(o);
}
} void init() {
clr(vis,0);
clr(setv,-1);
for(int i=0; i<=n; i++) mp[i]=last[i]=n+1;
} int main() {
while(scf("%d",&n)==1&&n) {
init();
int mex=0;
for(int i=1; i<=n; i++) {
int x;
scf("%d",&x);
arr[i]=x;
if(x<n) vis[x]=1;
while(vis[mex]) mex++;
b[i]=mex;
} for(int i=n; i>=1; i--) {
if(arr[i]<n) {
mp[i]=last[arr[i]]-1;
last[arr[i]]=i;
}
} // for(int i=1;i<=n;i++) prf("%d ",b[i]); puts("");
build(1,1,n); LL ans=sumv[1];
// bug(ans);
for(int i=1; i<n; i++) { if(arr[i]>=n) {
ans+=sumv[1];
} else {
_v=arr[i];
query(1,1,n);
// prf("%d,%d\n",_pos,mp[i]); if(_pos<=mp[i]){
ql=_pos,qr=mp[i];
_v2=arr[i];
update(1,1,n);
}
ans+=sumv[1];
}
// bug(ans);
} prf("%lld\n",ans);
}
return 0;
} //end-----------------------------------------------------------------------

Notes

枚举区间: dp[i]表示以i为右边界的所有区间的贡献。

HDU 4747 Mex 递推/线段树的更多相关文章

  1. HDU 3016 Man Down (线段树+dp)

    HDU 3016 Man Down (线段树+dp) Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Ja ...

  2. HDU.5692 Snacks ( DFS序 线段树维护最大值 )

    HDU.5692 Snacks ( DFS序 线段树维护最大值 ) 题意分析 给出一颗树,节点标号为0-n,每个节点有一定权值,并且规定0号为根节点.有两种操作:操作一为询问,给出一个节点x,求从0号 ...

  3. HDU.1556 Color the ball (线段树 区间更新 单点查询)

    HDU.1556 Color the ball (线段树 区间更新 单点查询) 题意分析 注意一下pushdown 和 pushup 模板类的题还真不能自己套啊,手写一遍才行 代码总览 #includ ...

  4. HDU.1166 敌兵布阵 (线段树 单点更新 区间查询)

    HDU.1166 敌兵布阵 (线段树 单点更新 区间查询) 题意分析 加深理解,重写一遍 代码总览 #include <bits/stdc++.h> #define nmax 100000 ...

  5. HDU.1394 Minimum Inversion Number (线段树 单点更新 区间求和 逆序对)

    HDU.1394 Minimum Inversion Number (线段树 单点更新 区间求和 逆序对) 题意分析 给出n个数的序列,a1,a2,a3--an,ai∈[0,n-1],求环序列中逆序对 ...

  6. HDU.1689 Just a Hook (线段树 区间替换 区间总和)

    HDU.1689 Just a Hook (线段树 区间替换 区间总和) 题意分析 一开始叶子节点均为1,操作为将[L,R]区间全部替换成C,求总区间[1,N]和 线段树维护区间和 . 建树的时候初始 ...

  7. hdu 1754 I Hate It 线段树 点改动

    // hdu 1754 I Hate It 线段树 点改动 // // 不多说,裸的点改动 // // 继续练 #include <algorithm> #include <bits ...

  8. hdu 1166 敌兵布阵 线段树 点更新

    // hdu 1166 敌兵布阵 线段树 点更新 // // 这道题裸的线段树的点更新,直接写就能够了 // // 一直以来想要进线段树的坑,结果一直没有跳进去,今天算是跳进去吧, // 尽管十分简单 ...

  9. R - Weak Pair HDU - 5877 离散化+权值线段树+dfs序 区间种类数

    R - Weak Pair HDU - 5877 离散化+权值线段树 这个题目的初步想法,首先用dfs序建一颗树,然后判断对于每一个节点进行遍历,判断他的子节点和他相乘是不是小于等于k, 这么暴力的算 ...

随机推荐

  1. 第三次随笔——虚拟机及Linux入门

    虚拟机及Linux入门 虚拟机的安装 对于虚拟机的概念我早有接触,但是从来没有真正的实践过,借这次作业机会我终于实践了虚拟机的安装,安装的过程较为顺利,但还是出现了以下问题: 无法选择64位的系统 解 ...

  2. 20155211 2016-2017-2 《Java程序设计》第2周学习总结

    20155211 2016-2017-2 <Java程序设计>第2周学习总结 教材学习内容总结 通过对教材的阅读,我理解到Java中对于整数,浮点数等类型的定义与c语言基本相同. 对字面常 ...

  3. 20155213 第十二周课堂作业MySort

    20155213 第十二周课堂作业MySort 作业要求 模拟实现Linux下Sort -t : -k 2的功能 参考 Sort的实现 提交码云链接和代码运行截图 初始代码 1 import java ...

  4. 20155338 《JAVA程序设计》实验五网络编程与安全实验报告

    20155338 <JAVA程序设计>实验五网络编程安全实验报告 实验内容 实验一: •两人一组结对编程: •结对实现中缀表达式转后缀表达式的功能 MyBC.java •结对实现从上面功能 ...

  5. installshield 判断mdmcpq.inf和usbser.sys 是否 存在

    1.产品上位机程序,需要驱动支持,在安装  exe程序的时候,连同NET框架4.0和 .inf驱动文件,一起安装, 安装驱动的时候,会发现, 如果系统 C:\Windows\Inf 缺少mdmcpq. ...

  6. zabbix最新版3.4搭建(根据官方文档适当修改)

    操作系统:CentOS Linux release 7.4.1708 (Core) 1.安装apache 1.1 安装apache yum install httpd httpd-devel 1.2 ...

  7. day4 CSS属性操作

    1.CSS属性 基本属性 height, 高度 百分比 width, 宽度 像素,百分比 text-align:ceter, 水平方向居中 line-height, 垂直方向根据标签高度 color. ...

  8. 解决数据库SUSPECT(置疑)状态

    在虚拟机中运行数据库不小心强制关机了,结果有一个重要的数据库后面加上了一个suspect的关键字,在管理器中打不开,程序也不能运行. 网上有很多分析的方法,试了一些不管用,最后用这种方法解决了,记录一 ...

  9. 拼多多商品id怎么查看 拼多多店铺ID怎样看

    网上开店平台有很多编号.id等可以区分商品和店铺的标志,拼多多有店铺id也有商品id,这是两个不同的概念,店铺id进入到拼多多店铺即可查询,拼多多商品id怎么查看 拼多多店铺ID怎样看,那么拼多多商品 ...

  10. katalon系列十:Katalon Studio自定义关键字之拖拽

    Katalon Studio自带关键字“Drag And Drop To Object”,可以在这个网站实践:http://jqueryui.com/droppable/#default 不过“Dra ...