题目大意:一个数列若能在有限次数内删空,则称这个数列可以删空,一次删除操作定义如下:

记当前数列长度为$k$,则删掉数列中所有等于$k$的数。

现在有一个长度为$n$的数列$a$,有$m$次修改操作,为单点变值/整体增加或者减少$1$,问每次修改后,最少需要修改序列中多少个数,使得序列可以被删除。

数据范围:$n≤150000$。

我们首先考虑下最少需要修改的次数,我们设$b[i]$为数列$a$中填写了i的值得数量。

对于每一个$i$,我们可以用$b[i]$这么多数,覆盖区间$[i-b[i]+1,i]$。最终的答案就是未被覆盖的格子数量。

证明显然。

基于这个结论,我们就可以在$O(n)$的复杂度内求出一个序列$a$对应的答案,可以获得47分的好成绩。

在只有单点修改的情况下,我们发现我们可以用线段树做一下维护,就可以获得60分的好成绩。

我们发现,整体的$+1$或者$-1$,可以转化为查询的区间出现了移动,移动完查询区间后,我们更新一下两端的值即可。

这么搞就可以过掉这一题了。

时间复杂度:$O(n\log\ n)$。

 #include<bits/stdc++.h>
#define M (1<<19)
using namespace std; struct seg{int l,r,tag,minn,cnt;}a[M<<];
void pushup(int x){
a[x].minn=min(a[x<<].minn,a[x<<|].minn);
a[x].cnt=(a[x].minn==a[x<<].minn?a[x<<].cnt:)+(a[x].minn==a[x<<|].minn?a[x<<|].cnt:);
}
void upd(int x,int k){a[x].minn+=k; a[x].tag+=k;}
void pushdown(int x){if(a[x].tag) upd(x<<,a[x].tag),upd(x<<|,a[x].tag); a[x].tag=;} void build(int x,int l,int r){
a[x].l=l; a[x].r=r; if(l==r) return void(a[x].cnt=);
int mid=(l+r)>>;
build(x<<,l,mid); build(x<<|,mid+,r);
pushup(x);
}
void updata(int x,int l,int r,int k){
if(l<=a[x].l&&a[x].r<=r) return upd(x,k);
pushdown(x); int mid=(a[x].l+a[x].r)>>;
if(l<=mid) updata(x<<,l,r,k);
if(mid<r) updata(x<<|,l,r,k);
pushup(x);
}
void updata(int x,int id,int k){return updata(x,id,id,k);}
int query(int x,int l,int r){
if(a[x].minn>) return ;
if(l<=a[x].l&&a[x].r<=r) return a[x].cnt;
pushdown(x); int mid=(a[x].l+a[x].r)>>,cnt=;
if(l<=mid) cnt+=query(x<<,l,r);
if(mid<r) cnt+=query(x<<|,l,r);
return cnt;
} int num[M],n,q,m,orzorz[M*]={};
int *cnt=orzorz+M;
int main(){
scanf("%d%d",&n,&q);
for(int i=;i<=n;i++) scanf("%d",num+i),cnt[num[i]]++;
int T=max(n,q),m=T+n+q+,move=;
build(,,m);
for(int i=;i<=n;i++) updata(,T+i-cnt[i]+,T+i,);
while(q--){
int p,x; scanf("%d%d",&p,&x);
if(p>){
x-=move;
if(num[p]+move>=&&num[p]+move<=n)
updata(,num[p]-cnt[num[p]]++T,-);
cnt[num[p]]--; num[p]=x; cnt[num[p]]++;
updata(,num[p]-cnt[num[p]]++T,);
}else{
if(x<) move--;
updata(,-move-cnt[-move]++T,-move+T,x);
updata(,n-move-cnt[n-move]++T,n-move+T,-x);
if(x>) move++;
}
printf("%d\n",query(,T-move+,T-move+n));
}
}

【BJOI2019】删数 线段树的更多相关文章

  1. [Luogu5324][BJOI2019]删数(线段树)

    CF风格题,先猜结论,记数列中i这个数共出现了cnt[i]次,那么所有区间[i-cnt[i]+1,i]的并集的补集大小就是答案. 于是我们只需要线段树维护每个位置是否被某个区间覆盖到即可,对于整体加减 ...

  2. [BJOI2019]删数(线段树)

    [BJOI2019]删数(线段树) 题面 洛谷 题解 按照值域我们把每个数的出现次数画成一根根的柱子,然后把柱子向左推导,\([1,n]\)中未被覆盖的区间长度就是答案. 于是问题变成了单点修改值,即 ...

  3. [BJOI2019] 删数 [dp转贪心结论+线段树]

    题面 传送门 思路 dp部分 以下称合法序列为原题面中可以删空的序列 这个是我在模拟考场上的思路 一开始我是觉得,这个首先可以写成一个dp的形式:$dp[i][j]$表示用$j$个数字填满了目标序列的 ...

  4. Luogu5324 BJOI2019删数(线段树)

    考虑无修改怎么做.对于1~n的每个数,若其存在,将最后一个放在其值的位置,剩余在其前面依次排列,答案即为值域1~n上没有数的位置个数.带修改显然记一下偏移量线段树改一改就好了. #include< ...

  5. luogu P5324 [BJOI2019]删数

    传送门 不如先考虑暴力,能删的序列首先有\(1,2,3...n\),还有就是升序排序后从后往前放数,第\(i\)位要么放\(i\),要么放\(i+1\)位置的数,例如\(1,2,4,4,5,6,9,9 ...

  6. 题解 洛谷 P5324 【[BJOI2019]删数】

    先考虑对于一个序列,能使其可以删空的的修改次数. 首先可以发现,序列的排列顺序是没有影响的,所以可以将所有数放到桶里来处理. 尝试对一个没有经过修改的可以删空的序列来进行删数,一开始删去所有的\(n\ ...

  7. Problem 1007 幸运数 线段树成段更新

    题目链接: 题目 Problem 1007 幸运数 Time Limit: 2000 mSec Memory Limit : 131072 KB 问题描述 皮特的幸运数是2和5.只由幸运数字2和5组成 ...

  8. [BJOI2019] 删数

    https://www.luogu.org/problemnew/show/P5324 题解 首先我们需要弄清这个答案是什么. 对于一个长度为n的序列,那么它先删的肯定是\(n\),删完之后它就会跳到 ...

  9. hdu 4417 区间内比h小的数 线段树

    题意求区间内比h小的数的个数 将所有的询问离线读入之后,按H从小到大排序.然后对于所有的结点也按从小到大排序,然后根据查询的H,将比H小的点加入到线段树,然后就是一个区间和. 2015-07-27:专 ...

随机推荐

  1. Ubuntu安装软件提示boot空间不足

    用sudo apt-get install gitlab-ci-multi-runner安装应用都会出现“gzip: stdout: No space left on device”的问题. boot ...

  2. 650. 2 Keys Keyboard复制粘贴的次数

    [抄题]: Initially on a notepad only one character 'A' is present. You can perform two operations on th ...

  3. react项目搭建

    1.下载安装node.js,需要node.js环境. 2.经过挑选,决定选择creat-react-app这个项目脚手架,然后输入指令安装          $ npm install -g crea ...

  4. IMU

    (1)用IMU来进行预测 读入一个10/20帧的数据集,通过IMU来初步预测出位姿以及显示其路径. Christian Forster, Luca Carlone, Frank Dellaert, D ...

  5. Spring事务管理的配置

    spring-datasource-config.xml配置事务 <bean id="txManager" class="org.springframework.j ...

  6. Vmware unknow Interface ens33

    vmare打开虚拟网络编辑器,按图示操作

  7. CentOS 7 查询yum安装的软件及路径

    来源:CentOS 7 查询yum安装的软件及路径 先执行下面的命令,查看所有的已安装软件名称. rpm -qa 然后执行 rpm -ql 软件名称 就可以显示软件的安装路径.   [root@loc ...

  8. boost asio 网络聊天 代码修改学习

    简化asio的聊天代码 去除ROOM的设计 所有连接客户端均在同一个ROOM下 /*********************************************************** ...

  9. 重写equals和hashCode的方法

    为什么要有 hashCode引用 我们以"HashSet 如何检查重复"为例子来说明为什么要有 hashCode: 当你把对象加入 HashSet 时,HashSet 会先计算对象 ...

  10. IDEA下Spring Boot显示Run Dashboard面板

    在 .idea/workspace.xml 文件中找到 <component name="RunDashboard"> <option name="ru ...