题目链接:

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. Iframe 定义内联的子窗口(框架)

    1.Iframe 定义内联的子窗口(框架),用于在网页内显示网页 语法: <iframe src="URL"></iframe>URL 指向隔离页面的位置, ...

  2. npm audit fix

    执行npm install 出现如下提醒   added 253 packages from 162 contributors and audited 1117 packages in 42.157s ...

  3. PyQt5 signal and slot

    PyQt5 的 signal 与 slot 有所改变,例如,先定义一个 ZeroSignal 类: class ZeroSignal(QObject): atzero = pyqtSignal(int ...

  4. ABAP ODATA 文字列からxstringへの変換およびその逆変換(UTF-8)

    DATA(lv_str) = |Teststring|. TRY. * string -> xstring * default UTF-8 DATA(lv_xstr) = cl_abap_cod ...

  5. go-处理字符串导致内存溢出

    今日用go来做字符的“+”连接操作,每次连接的字符串大致有10M左右,循环连接100次,直接导致go内存溢出了. // Text project main.go package main import ...

  6. java课堂实践(5月17日)20155317 王新玮

    对P145 MathTool.java 代码托管 在IDEA中,使用JUnit进行单元测试,测试用例不少于三个,要包含正常情况,边界情况.提交测试代码和运行结果截图,加上学号水印,提交码云代码链接. ...

  7. 2.Rest Server提供数据库的Json字符串

    Delphi最大的特点是数据库操作便捷.为了能够给App提供数据,这里采用Rest Server后台,然后在用Json文件发送到APP前台. 1.后台的dataset转换为json. 这里百度后就可以 ...

  8. JDK1.7的HashMap的put(key, value)源码剖析

    目录 HashMap的put操作源码解析 1.官方文档 2.put(key, value) 3.完结 HashMap的put操作源码解析 1.官方文档 1.1.继承结构 java.lang.Objec ...

  9. 【MongoDB】NoSQL Manager for MongoDB 教程(基础篇)

    前段时间,学习了一下mongodb,在客户端工具方面,个人认为 NoSQL Manager for MongoDB 是体验比较好的一个,功能也较齐全.可惜在找教程的时候,发现很难找到比较详细的教程,也 ...

  10. OpenCV中对Mat里面depth,dims,channels,step,data,elemSize和数据地址计算的理解

    原文:OpenCV中对Mat里面depth,dims,channels,step,data,elemSize和数据地址计算的理解 Title : cv::Mat depth/dims/channels ...