题目链接:

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. error:0906D064:PEM routines:PEM_read_bio:bad base64 decode

    今天在使用easywechat对接企业打款到银行卡时,遇到了两个错误 error:0906D064:PEM routines:PEM_read_bio:bad base64 decode 和 erro ...

  2. PyAutoGui 中遇到的KeyError : DISPLAY

    实际情形有可能是: tests/test_enlighten.py:: in <module> import re, sys, signal, logging, argparse, pya ...

  3. iOS开发者证书-详解/生成/使用

    本文假设你已经有一些基本的Xcode开发经验, 并注册了iOS开发者账号. 相关基础 加密算法 现代密码学中, 主要有两种加密算法: 对称密钥加密 和 公开密钥加密. 对称密钥加密 对称密钥加密(Sy ...

  4. sublime install package没反应,以及安装后没有出现install package选项

    离线安装Package Control 一般出现这种问题的是网络原因,我们可以下载离线安装包 连接地址:https://github.com/wbond/package_control 安装完成后解压 ...

  5. pyhton习题20190201

    #20190131'''检查ipV4的有效性,有效则返回True,否则返回False,(提示使用split函数进行分割)'''import osdef print_ping_ip(ip): s = o ...

  6. 2016-2017-2 20155227实验二《Java面向对象程序设计》实验报告

    2016-2017-2 20155227实验二<Java面向对象程序设计>实验报告 实验内容 初步掌握单元测试和TDD 理解并掌握面向对象三要素:封装.继承.多态 初步掌握UML建模 熟悉 ...

  7. Java集合——LinkedList源码详解

    )LinkedList直接继承于AbstractSequentialList,同时实现了List接口,也实现了Deque接口. AbstractSequentialList为顺序访问的数据存储结构提供 ...

  8. 优步UBER司机全国各地奖励政策汇总 (4月11日-4月17日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  9. 【转载】Direct3D基础知识

    原文:Direct3D基础知识 重新从头开始学习DX,以前太急于求成了,很多基础知识都没掌握就开始写程序了,结果出了问题很难解决.   1.       D3D体系结构 D3D与GDI处与同一层次,区 ...

  10. day 10 文件

    1.文本文件 ,二进制文件 二进制文件:用vi 打开一个图片,MP3,视频 2.文件打开方式 # 重定向 文件不存在 文件存在 r error 文件开头 w 相当于 > 创建 覆盖,删除以前的内 ...