HDU 4747 Mex 递推/线段树
题目链接:
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 递推/线段树的更多相关文章
- HDU 3016 Man Down (线段树+dp)
HDU 3016 Man Down (线段树+dp) Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Ja ...
- HDU.5692 Snacks ( DFS序 线段树维护最大值 )
HDU.5692 Snacks ( DFS序 线段树维护最大值 ) 题意分析 给出一颗树,节点标号为0-n,每个节点有一定权值,并且规定0号为根节点.有两种操作:操作一为询问,给出一个节点x,求从0号 ...
- HDU.1556 Color the ball (线段树 区间更新 单点查询)
HDU.1556 Color the ball (线段树 区间更新 单点查询) 题意分析 注意一下pushdown 和 pushup 模板类的题还真不能自己套啊,手写一遍才行 代码总览 #includ ...
- HDU.1166 敌兵布阵 (线段树 单点更新 区间查询)
HDU.1166 敌兵布阵 (线段树 单点更新 区间查询) 题意分析 加深理解,重写一遍 代码总览 #include <bits/stdc++.h> #define nmax 100000 ...
- HDU.1394 Minimum Inversion Number (线段树 单点更新 区间求和 逆序对)
HDU.1394 Minimum Inversion Number (线段树 单点更新 区间求和 逆序对) 题意分析 给出n个数的序列,a1,a2,a3--an,ai∈[0,n-1],求环序列中逆序对 ...
- HDU.1689 Just a Hook (线段树 区间替换 区间总和)
HDU.1689 Just a Hook (线段树 区间替换 区间总和) 题意分析 一开始叶子节点均为1,操作为将[L,R]区间全部替换成C,求总区间[1,N]和 线段树维护区间和 . 建树的时候初始 ...
- hdu 1754 I Hate It 线段树 点改动
// hdu 1754 I Hate It 线段树 点改动 // // 不多说,裸的点改动 // // 继续练 #include <algorithm> #include <bits ...
- hdu 1166 敌兵布阵 线段树 点更新
// hdu 1166 敌兵布阵 线段树 点更新 // // 这道题裸的线段树的点更新,直接写就能够了 // // 一直以来想要进线段树的坑,结果一直没有跳进去,今天算是跳进去吧, // 尽管十分简单 ...
- R - Weak Pair HDU - 5877 离散化+权值线段树+dfs序 区间种类数
R - Weak Pair HDU - 5877 离散化+权值线段树 这个题目的初步想法,首先用dfs序建一颗树,然后判断对于每一个节点进行遍历,判断他的子节点和他相乘是不是小于等于k, 这么暴力的算 ...
随机推荐
- Iframe 定义内联的子窗口(框架)
1.Iframe 定义内联的子窗口(框架),用于在网页内显示网页 语法: <iframe src="URL"></iframe>URL 指向隔离页面的位置, ...
- npm audit fix
执行npm install 出现如下提醒 added 253 packages from 162 contributors and audited 1117 packages in 42.157s ...
- PyQt5 signal and slot
PyQt5 的 signal 与 slot 有所改变,例如,先定义一个 ZeroSignal 类: class ZeroSignal(QObject): atzero = pyqtSignal(int ...
- ABAP ODATA 文字列からxstringへの変換およびその逆変換(UTF-8)
DATA(lv_str) = |Teststring|. TRY. * string -> xstring * default UTF-8 DATA(lv_xstr) = cl_abap_cod ...
- go-处理字符串导致内存溢出
今日用go来做字符的“+”连接操作,每次连接的字符串大致有10M左右,循环连接100次,直接导致go内存溢出了. // Text project main.go package main import ...
- java课堂实践(5月17日)20155317 王新玮
对P145 MathTool.java 代码托管 在IDEA中,使用JUnit进行单元测试,测试用例不少于三个,要包含正常情况,边界情况.提交测试代码和运行结果截图,加上学号水印,提交码云代码链接. ...
- 2.Rest Server提供数据库的Json字符串
Delphi最大的特点是数据库操作便捷.为了能够给App提供数据,这里采用Rest Server后台,然后在用Json文件发送到APP前台. 1.后台的dataset转换为json. 这里百度后就可以 ...
- JDK1.7的HashMap的put(key, value)源码剖析
目录 HashMap的put操作源码解析 1.官方文档 2.put(key, value) 3.完结 HashMap的put操作源码解析 1.官方文档 1.1.继承结构 java.lang.Objec ...
- 【MongoDB】NoSQL Manager for MongoDB 教程(基础篇)
前段时间,学习了一下mongodb,在客户端工具方面,个人认为 NoSQL Manager for MongoDB 是体验比较好的一个,功能也较齐全.可惜在找教程的时候,发现很难找到比较详细的教程,也 ...
- OpenCV中对Mat里面depth,dims,channels,step,data,elemSize和数据地址计算的理解
原文:OpenCV中对Mat里面depth,dims,channels,step,data,elemSize和数据地址计算的理解 Title : cv::Mat depth/dims/channels ...