dtoi4375「BJOI2019」删数

题意:

对于任意一个数列,如果能在有限次进行下列删数操作后将其删为空数列,则称这个数列可以删空。一次删数操作定义如下:

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

现有一个长度为 n 的数列 a,有 m 次修改操作,第 i 次修改后你要回答:经过 i 次修改后的数列 a,至少还需要修改几个数才可删空?

每次修改操作为单点修改或数列整体加一或数列整体减一。

题解:

     如果一个我要删去大小为a的数,那么序列长度会变成a-h[a](h[a]为数值a出线的次数)。那么我们意会一下这个情况,我们可以想象成有h[a]个箱子堆在了a上面,然后向左倾倒,一个一个地落在位置上。当然,大于序列长度的位置的箱子不能考虑进来。

那么答案是什么?答案就是没有箱子的位置数量。因为我可以把堆了多个箱子的位置上的箱子移到没有箱子的地方,移动次数也就是答案。

那么如果只有单点修改的话,我们用一个线段树维护一下就好了。

然而有数列整体加减1怎么办呢。没有关系,我们只需要当成数字没变,询问的区间位移了就可以了。当然,后加入的数字要跟着位移。

于是我们又可以使用线段树维护了!

#include<cstdio>
#include<algorithm>
#include<cstdlib>
using namespace std;
const int INF=300000;
int n,m,a[300002],h[900002],t,cnt=1,minn,ans;
typedef struct{
    int ls,rs,Min,sum,f;
}P;
P p[4000002];
void pushdown(int root){
    if (p[root].f)
    {
        if (p[root].ls)
        {
            p[p[root].ls].Min+=p[root].f;p[p[root].ls].f+=p[root].f;
        }
        if (p[root].rs)
        {
            p[p[root].rs].Min+=p[root].f;p[p[root].rs].f+=p[root].f;
        }
        p[root].f=0;
    }
}
void build(int root,int begin,int end){
    if (begin==end)
    {
        p[root].Min=0;p[root].sum=1;
        return;
    }
    int mid=begin+(end-begin)/2;
    p[root].ls=++cnt;p[root].rs=++cnt;
    build(p[root].ls,begin,mid);build(p[root].rs,mid+1,end);
    int ls=p[root].ls,rs=p[root].rs;
    if (p[ls].Min<p[rs].Min){p[root].Min=p[ls].Min;p[root].sum=p[ls].sum;}
    else if (p[ls].Min>p[rs].Min){p[root].Min=p[rs].Min;p[root].sum=p[rs].sum;}
    else if (p[ls].Min==p[rs].Min){p[root].Min=p[ls].Min;p[root].sum=p[ls].sum+p[rs].sum;}
}
void gengxin(int root,int begin,int end,int begin2,int end2,int x){
    if (begin>end2 || end<begin2)return;
    if (begin>=begin2 && end<=end2)
    {
        p[root].Min+=x;p[root].f+=x;
        return;
    }
    int mid=begin+(end-begin)/2;pushdown(root);
    gengxin(p[root].ls,begin,mid,begin2,end2,x);gengxin(p[root].rs,mid+1,end,begin2,end2,x);
    int ls=p[root].ls,rs=p[root].rs;
    if (p[ls].Min<p[rs].Min){p[root].Min=p[ls].Min;p[root].sum=p[ls].sum;}
    else if (p[ls].Min>p[rs].Min){p[root].Min=p[rs].Min;p[root].sum=p[rs].sum;}
    else if (p[ls].Min==p[rs].Min){p[root].Min=p[ls].Min;p[root].sum=p[ls].sum+p[rs].sum;}
}
void chaxun(int root,int begin,int end,int begin2,int end2){
    if (begin>end2 || end<begin2)return;
    if (begin>=begin2 && end<=end2)
    {
        if (p[root].Min<minn)
        {
            minn=p[root].Min;ans=p[root].sum;
        }
        else if (p[root].Min==minn)ans+=p[root].sum;
        return;
    }
    int mid=begin+(end-begin)/2;pushdown(root);
    chaxun(p[root].ls,begin,mid,begin2,end2);chaxun(p[root].rs,mid+1,end,begin2,end2);
}
int main()
{
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++){scanf("%d",&a[i]);h[a[i]+INF]++;}
    t=n;build(1,-INF,INF);
    for (int i=1;i<=n;i++)
    if (h[i+INF])gengxin(1,-INF,INF,i-h[i+INF]+1,i,1);
    for (int i=1;i<=m;i++)
    {
        int op,x;
        scanf("%d%d",&op,&x);
        if (op)
        {
            if (h[a[op]+INF] && a[op]<=t)gengxin(1,-INF,INF,a[op]-h[a[op]+INF]+1,a[op]-h[a[op]+INF]+1,-1);
            h[a[op]+INF]--;x=t-n+x;h[x+INF]++;
            if (h[x+INF])gengxin(1,-INF,INF,x-h[x+INF]+1,x-h[x+INF]+1,1);
            a[op]=x;
        }
        else
        {
            if (x==-1)
            {
                t++;
                if (h[t+INF])gengxin(1,-INF,INF,t-h[t+INF]+1,t,1);
            }
            else
            {
                if (h[t+INF])gengxin(1,-INF,INF,t-h[t+INF]+1,t,-1);
                t--;
            }
        }
        minn=INF;ans=0;
        chaxun(1,-INF,INF,t-n+1,t);
        if (minn)puts("0");else printf("%d\n",ans);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/1124828077ccj/p/12241880.html

时间: 2024-10-09 07:00:19

dtoi4375「BJOI2019」删数的相关文章

「CQOI2015」选数

「CQOI2015」选数 题目描述 我们知道,从区间[L,H](L和H为整数)中选取N个整数,总共有(H-L+1)^N种方案.小z很好奇这样选出的数的最大公约数的规律,他决定对每种方案选出的N个整数都求一次最大公约数,以便进一步研究.然而他很快发现工作量太大了,于是向你寻求帮助.你的任务很简单,小z会告诉你一个整数K,你需要回答他最大公约数刚好为K的选取方案有多少个.由于方案数较大,你只需要输出其除以1000000007的余数即可. 输入输出格式 输入格式: 输入一行,包含4个空格分开的正整数,

「BJOI2019」奥术神杖

「BJOI2019」奥术神杖 Bezorath 大陆抵抗地灾军团入侵的战争进入了僵持的阶段,世世代代生活在 Bezorath 这片大陆的精灵们开始寻找远古时代诸神遗留的神器,试图借助神器的神秘力量帮助她们战胜地灾军团. 在付出了惨痛的代价后,精灵们从步步凶险的远古战场取回了一件保存尚完好的神杖.但在经历过那场所有史书都视为禁忌的“诸神黄昏之战”后,神杖上镶嵌的奥术宝石已经残缺,神力也几乎消耗殆尽.精灵高层在至高会议中决定以举国之力收集残存至今的奥术宝石,并重金悬赏天下能工巧匠修复这件神杖. 你作

「SCOI2009」windy数

传送门 Luogu 解题思路 数位 \(\text{DP}\) 设状态 \(dp[now][las][0/1][0/1]\) 表示当前 \(\text{DP}\) 到第 \(i\) 位,前一个数是 \(las\),有没有顶到上界,有没有前导零的答案. 转移十分显然. 细节注意事项 咕咕咕 参考代码 #include <algorithm> #include <iostream> #include <cstring> #include <cstdlib> #i

「递归」求第n个斐波纳契数

用「递归」方法求第n个斐波纳契数 1 #include<stdio.h> 2 long int dog(int p) 3 { 4 if(p>1) 5 return dog(p-1)+dog(p-2); 6 else if (p==1||p==0) 7 return 1; 8 } 9 int main() 10 { 11 printf("您要求第几个斐波纳契数:\n"); 12 int n; 13 scanf("%d",&n); 14 pri

「ZJOI2018」历史

「ZJOI2018」历史 前置知识 \(\text{LCT}\) 维护子树信息,考虑辅助树上一个节点的子树信息只是其代表的这一段链的信息,设 \(S(u)\) 为节点 \(u\) 的子树信息,那么在辅助树上我们维护的是: \[ S(u)=S(lson)+S(rson)+val(u) \] 考虑它们的实际意义 \(lson\) 是 \(u\) 的父亲,\(rson\) 是 \(u\) 的重儿子,显然 \(S(lson)\) 是我们不需要的,而真正的辅助信息只算了节点本身和重儿子. 考虑按照这样算的

「ZJOI2017」仙人掌

「ZJOI2017」仙人掌 题目大意: 给定一张无向联通图,求有多少种本质不同的不加重边的加边方案使得新图是个仙人掌. 解题思路: 如果原来的图不是仙人掌,那么答案就是 \(0\) ,否则求出这个仙人掌的无向图 \(\text{dfs}\) 树,任何一条新边都不能覆盖原来已经被覆盖过的边.那么只要把已经覆盖过得边删掉,变成若干棵树的问题,答案就是每棵树的答案的乘积. 一棵树的做法有一个很厉害的转化,因为题目要求不能有重边,我们可以允许转移加重边,并且每条树边必须被覆盖.然后会发现把每一种这样的方

「mac」释放 macOS 菜单栏潜能的软件们(十四款) 19.3.13 删除一款

转至:持续文章更新列表,建议收藏 一款好的软件不但可以节约时间,更能让你体验系统的魅力. 想知道我的 Mac 菜单栏都有什么嘛?这是一篇简单的介绍 Mac 菜单栏工具的文章,共计 15 款,每一款点击都可以直达官网. 大多数软件都提供适用版本,建议先行试用在决定是否购买,如没有试用版可以回复你的问题询问详情! 只有最适合你的应用,才称得上是效率应用. 尝新者:尝试一切新鲜的事物 题图就是我的菜单栏啦! 要知道菜单栏堆积,的确就如同 iOS 上软件从不排序一样令人不快,无法快速找到想要的对应应用,

大数据和「数据挖掘」是何关系?---来自知乎

知乎用户,互联网 244 人赞同 在我读数据挖掘方向研究生的时候:如果要描述数据量非常大,我们用Massive Data(海量数据)如果要描述数据非常多样,我们用Heterogeneous Data(异构数据)如果要描述数据既多样,又量大,我们用Massive Heterogeneous Data(海量异构数据)--如果要申请基金忽悠一笔钱,我们用Big Data(大数据) 编辑于 2014-02-2817 条评论感谢 收藏没有帮助举报作者保留权利 刘知远,NLPer 4 人赞同 我觉得 大数据

LibreOJ #2006. 「SCOI2015」小凸玩矩阵

二次联通门 : LibreOJ #2006. 「SCOI2015」小凸玩矩阵 /* LibreOJ #2006. 「SCOI2015」小凸玩矩阵 本来以为是道数据结构题 后来想了想发现不可做 就考虑二分dp判断 推方程推不出来 就考虑用网络流判断了 二分出一个数 将小于这个数的位置的点编号 每行的可行点与下一行可行的点连边 后一边最大流判断可选出的数的个数是否符合要求即可 */ #include <cstdio> #include <iostream> #include <q