Mex

Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)
Total Submission(s): 2482    Accepted Submission(s): 805

Problem Description
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.

 
Input
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.
 
Output
For each test case, output one line containing a integer denoting the answer.
 
Sample Input
3
0 1 3
5
1 0 2 0 1
0
Sample Output
5
24
/*
hdu 4747 线段树 表示开始毫无头绪,总觉得和线段树扯不上什么关系- - 弱TAT 我们要求的是mex[i,j](i~j中不存在的最小非负整数)的和,观察可以发现对于1~n,
mex[1,i]是递增的,因为你当前mex值可以在后面出现 然后假设去掉a[1],可以发现在a[1]再次出现之前.mex值大于a[1]的都会变成a[1]
1 0 2 0 1 -> 0 2 3 3 3
去掉a[1] -> 1 1 1 3 然后按照这个思路弄即可,先处理出mex[1,i]的情况并插入线段树,然后处理出a[i]下次
出现的位置。 利用线段树可以求出在a[i]再次出现之前比a[i]大的最小位置,把这段
全部置为a[i](毕竟这个序列是递增的),并能快速求出和. hhh-2016-03-24 18:15:48
*/
#include <algorithm>
#include <cmath>
#include <queue>
#include <iostream>
#include <cstring>
#include <map>
#include <cstdio>
#include <vector>
#include <functional>
#define lson (i<<1)
#define rson ((i<<1)|1)
using namespace std;
typedef long long ll;
const int maxn = 500550;
struct node
{
int l,r;
ll num;
int Max,add;
int mid()
{
return ((l+r)>>1);
};
} tree[maxn<<2]; int a[maxn],nex[maxn],mex[maxn];
map<int,int> mp; void update_up(int i)
{
tree[i].num = tree[lson].num+tree[rson].num;
tree[i].Max = max(tree[lson].Max,tree[rson].Max);
} void build(int i,int l,int r)
{
tree[i].l = l,tree[i].r = r;
tree[i].add = 0;
if(l == r)
{
tree[i].num = mex[l];
tree[i].Max = mex[l];
return ;
}
int mid = tree[i].mid();
build(lson,l,mid);
build(rson,mid+1,r);
update_up(i);
} void update_down(int i)
{
if(tree[i].add)
{
tree[lson].add = 1;
tree[rson].add = 1;
tree[lson].num = (ll)tree[i].Max*(tree[lson].r-tree[lson].l+1);
tree[rson].num = (ll)tree[i].Max*(tree[rson].r-tree[rson].l+1);
tree[lson].Max= tree[i].Max;
tree[rson].Max= tree[i].Max;
tree[i].add = 0;
}
}
void Insert(int i,int l,int r,int val)
{
if(tree[i].l >= l && r >= tree[i].r)
{
tree[i].num = (ll)(tree[i].r-tree[i].l+1)*val;
tree[i].Max = val;
tree[i].add = 1;
return;
}
update_down(i);
int mid = tree[i].mid();
if(l <= mid)
Insert(lson,l,r,val);
if(r > mid)
Insert(rson,l,r,val);
update_up(i);
}
int cur;
void get_k(int i,int k)
{
if(tree[i].l == tree[i].r)
{
cur = tree[i].l;
return ;
}
update_down(i);
//int mid = tree[i].mid();
if(k < tree[lson].Max)
get_k(lson,k);
else
get_k(rson,k);
update_up(i);
} ll query(int i,int l,int r)
{
if(tree[i].l >= l && r >= tree[i].r)
{
return tree[i].num;
}
update_down(i);
int mid = tree[i].mid();
ll ad = 0;
if(l <= mid)
ad += query(lson,l,r);
if(r > mid)
ad += query(rson,l,r);
update_up(i);
return ad;
} int main()
{
int n;
while(scanf("%d",&n) != EOF && n)
{
int flag= 0;
for(int i = 1; i <= n; i++)
{
scanf("%d",&a[i]);
} int t = 0;
mp.clear();
for(int i = 1; i <= n; i++)
{
mp[a[i]] = 1;
//cout << mp[t] <<endl ;
while(mp.find(t) != mp.end()) t++;
mex[i] = t;
} build(1,1,n);
mp.clear();
for(int i = n; i >= 1; i--)
{
if(mp[a[i]] == 0) nex[i] = n+1;
else nex[i] = mp[a[i]];
mp[a[i]] = i;
}
ll ans = 0;
for(int i = 1; i <= n; i++)
{
int nx = nex[i];
ans += query(1,i,n);
//cout << ans <<endl;
if(tree[1].Max > a[i])
{
get_k(1,a[i]);
if(cur < nx)
Insert(1,cur,nx-1,a[i]);
// cout << cur <<" "<<nx << " " << a[i] <<endl;
}
}
printf("%I64d\n",ans);
}
return 0;
} /*
Sample Input
3
0 1 3
5
1 0 2 0 1
0 Sample Output
5
24
*/

  

												

hdu 4747 线段树的更多相关文章

  1. hdu 4747 线段树/DP

    先是线段树 可以知道mex(i,i),mex(i,i+1)到mex(i,n)是递增的. 首先很容易求得mex(1,1),mex(1,2)......mex(1,n) 因为上述n个数是递增的. 然后使用 ...

  2. hdu 5877 线段树(2016 ACM/ICPC Asia Regional Dalian Online)

    Weak Pair Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total ...

  3. hdu 3974 线段树 将树弄到区间上

    Assign the task Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  4. hdu 3436 线段树 一顿操作

    Queue-jumpers Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) To ...

  5. hdu 3397 线段树双标记

    Sequence operation Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Othe ...

  6. hdu 4578 线段树(标记处理)

    Transformation Time Limit: 15000/8000 MS (Java/Others)    Memory Limit: 65535/65536 K (Java/Others) ...

  7. hdu 4533 线段树(问题转化+)

    威威猫系列故事——晒被子 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Tot ...

  8. hdu 2871 线段树(各种操作)

    Memory Control Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) T ...

  9. hdu 4052 线段树扫描线、奇特处理

    Adding New Machine Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Othe ...

随机推荐

  1. Ubuntu Desktop 16.04 LTS 下成功配置Jupyter的两个python内核版本(2.7x,3.5x)

    Ubuntu  Desktop 16.04 LTS 安装好系统默认就有python两个不同版本(2.7.12和3.5.2) 现在来熟悉一下jupyter的对python这两个不同python版本的内核 ...

  2. Python之旅.第二章数据类型 3.19/3.20/3.21/3.22/3.23

    一.数字类型 1.int类型: 基本使用: 用途:用于年龄,手机号,身份证号: 定义: age=18: 常用操作+内置方法: 正常的运算赋值: 进制转换: print(bin(3)); 把十进制3转换 ...

  3. Nagios监控的部署与配置

    [安装Nagios] yum install -y httpd httpd-devel httpd-tools mysql mysql-devel mysql-server php php-devel ...

  4. 新概念英语(1-63)Thank you, doctor.

    新概念英语(1-63)Thank you, doctor. Who else is in bed today? why? A:How's Jimmy today? B:Better. Thank yo ...

  5. SpringCloud的注解:EnableEurekaClient vs EnableDiscoveryClient

    What's the difference between EnableEurekaClient and EnableDiscoveryClient? In some applications, I ...

  6. mysql中的函数与存储过程

    mysql中的函数:1 mysql下创建函数: 1.1 语法: delimiter $$ -- 设置分隔符,默认是; 设置成其他符号,让编译器知道我们函数编写的结束,此处设置成$$ create fu ...

  7. 赛码网算法: 军训队列( python实现 )

    军训队列 题目描述某大学开学进行军训队列训练,将学生从一开始按顺序依次编号,并排成一行横队,训练的规则如下:从头开始一至二报数,凡报到二的出列剩下的依次向前靠拢,再从头开始进行一至三报数,凡报到三的出 ...

  8. Python之进程

    进程 进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础.在早期面向进程设计的计算机结构中,进程是程序的基本执行实体:在当代 ...

  9. 百度echarts使用--y轴label数字太长难以全部显示

    问题: 今天遇到个小问题,我们系统前端呈现使用了百度echarts.在绘制折线图的时候,因为数字过大,导致显示出现了问题. 解决方案: 左边y轴的值默认是根据我们填充进去的值来默认分割的,因为原始值就 ...

  10. IT技术有感

    今天看技术文章,spring相关的,某一个点以前每次看一直不理解, 可是不知道为什么隔了1年左右,中间什么都没做,现在却都懂了. 在看懂的那一刻,笼罩在我心上的躁动突然平静了许多,我的心这一年来前所未 ...