题目

分析

\(O(n)\)求出mex(1,i)(1<=i<=n):

虽然0<=ai<=10^9,但只有n个数,所以mex一定小于等于n
for(long long j=1;j<=n;j++)
{
if(a[j]<=n)
bz[a[j]]=false;
for(long long k=top;k<=n;k++)
{
if(bz[k])
{
top=k;
ans+=top;
break;
}
}
}

显然mex是单调不下降的,

接着用线段树维护mex。

如果删掉a[i],从下一个mex比a[i]大的位置到下一个a[i]的位置之前的mex都会改变,都会变成a[i]。

所以用线段树维护区间最大mex以及区间mex和。

#include <cmath>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <queue>
const long long maxlongint=2147483647;
const long long mo=1000000007;
const long long N=2010000;
using namespace std;
long long a[N],n,ans=0,next[N];
long long bz[N]={0};
struct ddx
{
long long sum,mxe,lazy;
}tree[N*4];
long long put(long long v,long long l,long long r,long long x,long long y)
{
if(l==r)
{
tree[v].mxe=tree[v].sum=y;
return 0;
}
long long mid=(l+r)/2;
if(x<=mid)
put(v*2,l,mid,x,y);
else
put(v*2+1,mid+1,r,x,y);
tree[v].sum=tree[v*2].sum+tree[v*2+1].sum;
tree[v].mxe=max(tree[v*2].mxe,tree[v*2+1].mxe);
}
long long findpos(long long v,long long l,long long r,long long x)
{
if(l==r)
{
if(tree[v].mxe>x)
return l;
else return maxlongint;
}
long long mid=(l+r)/2;
if(tree[v].lazy>=0)
{
tree[v*2].mxe=tree[v*2+1].mxe=tree[v*2].lazy=tree[v*2+1].lazy=tree[v].lazy;
tree[v*2].sum=tree[v].lazy*(mid-l+1);
tree[v*2+1].sum=tree[v].lazy*(r-mid);
tree[v].lazy=-1;
}
long long o=0;
if(tree[v*2].mxe>x)
o=findpos(v*2,l,mid,x);
else
o=findpos(v*2+1,mid+1,r,x);
tree[v].sum=tree[v*2].sum+tree[v*2+1].sum;
tree[v].mxe=max(tree[v*2].mxe,tree[v*2+1].mxe);
return o;
}
long long change(long long v,long long l,long long r,long long x,long long y,long long z)
{
if(l==x && y==r)
{
tree[v].sum=z*(r-l+1);
tree[v].mxe=z;
tree[v].lazy=z;
return 0;
}
long long mid=(l+r)/2;
if(tree[v].lazy>=0)
{
tree[v*2].mxe=tree[v*2+1].mxe=tree[v*2].lazy=tree[v*2+1].lazy=tree[v].lazy;
tree[v*2].sum=tree[v].lazy*(mid-l+1);
tree[v*2+1].sum=tree[v].lazy*(r-mid);
tree[v].lazy=-1;
}
if(y<=mid)
change(v*2,l,mid,x,y,z);
else
if(x>mid)
change(v*2+1,mid+1,r,x,y,z);
else
{
change(v*2,l,mid,x,mid,z);
change(v*2+1,mid+1,r,mid+1,y,z);
}
tree[v].sum=tree[v*2].sum+tree[v*2+1].sum;
tree[v].mxe=max(tree[v*2].mxe,tree[v*2+1].mxe);
}
long long find(long long v,long long l,long long r,long long x,long long y)
{
if(l==x && y==r)
{
ans+=tree[v].sum;
return 0;
}
long long mid=(l+r)/2;
if(tree[v].lazy>=0)
{
tree[v*2].mxe=tree[v*2+1].mxe=tree[v*2].lazy=tree[v*2+1].lazy=tree[v].lazy;
tree[v*2].sum=tree[v].lazy*(mid-l+1);
tree[v*2+1].sum=tree[v].lazy*(r-mid);
tree[v].lazy=-1;
}
if(y<=mid)
find(v*2,l,mid,x,y);
else
if(x>mid)
find(v*2+1,mid+1,r,x,y);
else
{
find(v*2,l,mid,x,mid);
find(v*2+1,mid+1,r,mid+1,y);
}
tree[v].sum=tree[v*2].sum+tree[v*2+1].sum;
tree[v].mxe=max(tree[v*2].mxe,tree[v*2+1].mxe);
}
int main()
{
scanf("%lld",&n);
for(long long i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
if(a[i]<=n)
{
next[bz[a[i]]]=i;
bz[a[i]]=i;
}
}
for(long long i=1;i<=n;i++)
if(!next[i])
next[i]=n+1;
memset(bz,true,sizeof(bz));
for(long long i=0;i<=N*4-1;i++)
tree[i].lazy=-1;
long long top=0;
ans=0;
for(long long j=1;j<=n;j++)
{
if(a[j]<=n)
bz[a[j]]=false;
for(long long k=top;k<=n;k++)
{
if(bz[k])
{
top=k;
ans+=top;
break;
}
}
put(1,1,n,j,top);
}
for(long long i=2;i<=n;i++)
{
if(a[i-1]<=n)
{
long long pos=findpos(1,1,n,a[i-1]);
if(next[i-1]-1>=pos)
change(1,1,n,pos,next[i-1]-1,a[i-1]);
}
find(1,1,n,i,n);
}
printf("%lld",ans);
}

【NOIP2016提高A组8.11】自然数的更多相关文章

  1. 【NOIP2016提高A组8.11】种树

    题目 分析 题目要求把图删点,删成树. 考虑一下树的定义,点数n=边数m+1 并且,树中点两两之间联通,那么选的点就不能是割点. 可以用tarjan将图中最大的联通块,保证其中点两两之间有不止一条路径 ...

  2. 【NOIP2016提高A组8.11】钱仓

    题目 分析 发现,一定有一个点作为起点,所有的路径都不经过这个起点. 接着贪心求答案, 如果\(c_i>1\),将其中\(c_i-1\)个钱往后"铺". 易证\(x^2+y^ ...

  3. JZOJ 【NOIP2016提高A组集训第16场11.15】兔子

    JZOJ [NOIP2016提高A组集训第16场11.15]兔子 题目 Description 在一片草原上有N个兔子窝,每个窝里住着一只兔子,有M条路径连接这些窝.更特殊地是,至多只有一个兔子窝有3 ...

  4. JZOJ 【NOIP2016提高A组集训第16场11.15】SJR的直线

    JZOJ [NOIP2016提高A组集训第16场11.15]SJR的直线 题目 Description Input Output Sample Input 6 0 1 0 -5 3 0 -5 -2 2 ...

  5. 5458. 【NOIP2017提高A组冲刺11.7】质数

    5458. [NOIP2017提高A组冲刺11.7]质数 (File IO): input:prime.in output:prime.out Time Limits: 1000 ms  Memory ...

  6. JZOJ 4732. 【NOIP2016提高A组模拟8.23】函数

    4732. [NOIP2016提高A组模拟8.23]函数 (Standard IO) Time Limits: 1500 ms  Memory Limits: 262144 KB  Detailed ...

  7. JZOJ 5462. 【NOIP2017提高A组冲刺11.8】好文章

    5462. [NOIP2017提高A组冲刺11.8]好文章 (File IO): input:article.in output:article.out Time Limits: 1000 ms  M ...

  8. JZOJ 5456. 【NOIP2017提高A组冲刺11.6】奇怪的队列

    5456. [NOIP2017提高A组冲刺11.6]奇怪的队列 (File IO): input:queue.in output:queue.out Time Limits: 1000 ms  Mem ...

  9. JZOJ 5459. 【NOIP2017提高A组冲刺11.7】密室

    5459. [NOIP2017提高A组冲刺11.7]密室 (File IO): input:room.in output:room.out Time Limits: 1000 ms  Memory L ...

随机推荐

  1. freemarker程序开发

    1.程序开发入门 1.1 创建配置实例 首先,你应该创建一个freemarker.template.Configuration的实例,然后调整它的设置.Configuration实例是存储FreeMa ...

  2. String.prototype.replace

    第一个参数是正则表达式 第二个参数是一个replacer 函数的入参如下: replacer(match,p1,p2,p3.. 其实也相当于 replacer($&,$1,$2,$3.. 资料 ...

  3. Cloudera-JDBC-Driver-for-Impala

    Cloudera-JDBC-Driver-for-Impala-Install-Guide-2-5-5.pdf https://github.com/FlowerBirds/flowerbirds.g ...

  4. Oracle 无备份情况下的恢复--控制文件/数据文件

    13.3无备份恢复控制文件 没有备份恢复控制文件其实就是在nomount状态,create control创建一个新的控制文件. dba必须知道4个信息才能正确的创建:数据库名.在线日志路径及其大小. ...

  5. $destroy——angular

    参考资料:[http://odetocode.com/blogs/scott/archive/2013/07/16/angularjs-listening-for-destroy.aspx]

  6. Redis的消息订阅及发布及事务机制

    Redis的消息订阅及发布及事务机制 订阅发布 SUBSCRIBE PUBLISH 订阅消息队列及发布消息. # 首先要打开redis-cli shell窗口 一个用于消息发布 一个用于消息订阅 # ...

  7. 多线程18-QueueUserWorkItem

        ));         }         ;             ;             ));             ThreadPool.QueueUserWorkItem(A ...

  8. mysqlreport 安装&使用

    安装包:mysqlreport-3.5.tgz 下载地址:http://hackmysql.com/scripts/mysqlreport-3.5.tgz 安装办法:[root@nagios ~]# ...

  9. adb 配置连接

    一. adb环境安装 1.1. windown 驱动安装 1. 下载驱动(ADB Kits):http://adbshell.com/downloads 2. adb 测试 <1>. 解压 ...

  10. 高级BASH

    Bash介绍与入门 1,简介 Bash(GNU Bourne-Again Shell)是一个为GNU计划编写的Unix shell,它是许多Linux平台默认使用的shell shell是一个命令解释 ...