Loading [MathJax]/jax/input/TeX/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >HDU 4747 Mex「建议收藏」

HDU 4747 Mex「建议收藏」

作者头像
全栈程序员站长
发布于 2022-07-07 13:04:19
发布于 2022-07-07 13:04:19
24700
代码可运行
举报
运行总次数:0
代码可运行

大家好,又见面了,我是全栈君。

题意:

给出一段数字a 定义mex(l,r)表示a[l]…a[r]中最小的不连续的数字 求出全部mex(l,r)的和

思路:

首先能够想到由l開始到n的全部数字的mex值必定是递增的 那么就能够求出以1開始到n的全部数字的mex 从前到后扫一遍就可以 这时能够求出[1,r]全部区间的mex和 利用线段树就可以

接着考虑怎样求[2,r]、[3,r]…. 由[1,r]到[2,r]的转变无非是去掉第一个数字 那么去掉一个数字的影响是什么呢?

比方去掉一个2 那他最多影响到下一个2出现的地方 并且 他仅仅是把mex>2的地方改成了2 即从2处截断 又由于之前所说的递增关系 所以影响的区间也一定是连续的!

那么我们就能够每次删掉一个数字 利用线段树找出他影响的区间 并把这个区间覆盖为那个删掉的数字

最后每次求和就是答案

代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
using namespace std;
typedef __int64 ll;
#define N 201000
#define L(x) (x<<1)
#define R(x) ((x<<1)|1)

struct node
{
    int l,r,val,lazy;
    ll sum;
}tree[N*4];
int a[N],mex[N],next[N];
int n,l,r;
map<int,int> mp;
ll ans;

void up(int i)
{
    tree[i].val=max(tree[L(i)].val,tree[R(i)].val);
    tree[i].sum=tree[L(i)].sum+tree[R(i)].sum;
}

void down(int i)
{
    if(tree[i].lazy!=-1)
    {
        tree[L(i)].lazy=tree[i].lazy;
        tree[L(i)].val=tree[i].lazy;
        tree[L(i)].sum=(tree[L(i)].r-tree[L(i)].l+1)*tree[i].lazy;
        tree[R(i)].lazy=tree[i].lazy;
        tree[R(i)].val=tree[i].lazy;
        tree[R(i)].sum=(tree[R(i)].r-tree[R(i)].l+1)*tree[i].lazy;
        tree[i].lazy=-1;
    }
}

void init(int l,int r,int i)
{
    tree[i].l=l; tree[i].r=r; tree[i].lazy=-1;
    if(l==r)
    {
        tree[i].val=mex[l];
        tree[i].sum=mex[l];
        return ;
    }
    int mid=(l+r)>>1;
    init(l,mid,L(i));
    init(mid+1,r,R(i));
    up(i);
}

void update(int l,int r,int i,int k)
{
    if(l==tree[i].l&&r==tree[i].r)
    {
        tree[i].sum=(tree[i].r-tree[i].l+1)*k;
        tree[i].val=k;
        tree[i].lazy=k;
        return ;
    }
    down(i);
    int mid=(tree[i].l+tree[i].r)>>1;
    if(r<=mid) update(l,r,L(i),k);
    else if(l>mid) update(l,r,R(i),k);
    else
    {
        update(l,mid,L(i),k);
        update(mid+1,r,R(i),k);
    }
    up(i);
}

void query(int i,int k)
{
    if(tree[i].l==tree[i].r)
    {
        if(tree[i].val>k) l=tree[i].l;
        else l=n+1;
        return ;
    }
    down(i);
    if(tree[L(i)].val>k) query(L(i),k);
    else query(R(i),k);
    up(i);
}

int main()
{
    int i,j;
    while(~scanf("%d",&n))
    {
        if(!n) break;
        mp.clear(); // get mex
        j=0;
        for(i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            mp[a[i]]=1;
            while(mp[j]) j++;
            mex[i]=j;
        }
        mp.clear(); // get next
        for(i=1;i<=n;i++) mp[a[i]]=n+1;
        for(i=n;i>=1;i--)
        {
            next[i]=mp[a[i]];
            mp[a[i]]=i;
        }
        //for(i=1;i<=n;i++) printf("%d %d\n",mex[i],next[i]);
        init(1,n,1);
        for(i=1,ans=0;i<=n;i++)
        {
            ans+=tree[1].sum;
            query(1,a[i]);
            r=next[i];
            //printf("%d %d\n",l,r);
            if(l<r)
            {
                update(l,r-1,1,a[i]);
            }
            update(i,i,1,0);
        }
        printf("%I64d\n",ans);
    }
    return 0;
}

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/116215.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022年1月2,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
HDU 3333 Turing Tree (线段树)
Turing Tree Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 4768    Accepted Submission(s): 1686 Problem Description After inventing Turing Tree, 3xian always felt boring when solving problems ab
ShenduCC
2018/04/27
5560
树套树专题——bzoj 3110: [Zjoi2013] K大数查询 &amp; 3236 [Ahoi2013] 作业 题解「建议收藏」
Time Limit: 20 Sec Memory Limit: 512 MB Submit: 978 Solved: 476
全栈程序员站长
2022/07/10
2450
4927 线段树练习5
时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold 题解  查看运行结果 题目描述 Description 有n个数和5种操作 add a b c:把区间[a,b]内的所有数都增加c set a b c:把区间[a,b]内的所有数都设为c sum a b:查询区间[a,b]的区间和 max a b:查询区间[a,b]的最大值 min a b:查询区间[a,b]的最小值 输入描述 Input Description 第一行两个整数n,m,第二行n个整数表示这n个数的初始值 接
attack
2018/04/12
7180
12:Challenge 5(线段树区间直接修改)
总时间限制: 10000ms单个测试点时间限制: 1000ms内存限制: 262144kB描述 给一个长为N的数列,有M次操作,每次操作是以下两种之一: (1)将某连续一段同时改成一个数 (2)求数列中某连续一段的和 输入第一行两个正整数N和M。 第二行N的整数表示这个数列。 接下来M行,每行开头是一个字符,若该字符为'M',则表示一个修改操作,接下来三个整数x、y和z,表示在[x,y]这段区间的数改为z;若该字符为'Q',则表示一个询问操作,接下来两个整数x和y,表示求[x,y]这段区间的和。输出对每一个
attack
2018/04/12
7820
【HDU - 4348】To the moon(主席树在线区间更新)
操作有四种, C l r d:更新区间[l,r],值都加上d,并且时间前进1 Q l r:查询[l,r]的区间和 H l r t:查询t时刻的区间和 B t:回到t时刻(一定是历史时刻),且t时刻之后的操作都作废了。
饶文津
2020/06/02
7620
HDU 5634 Rikka with Phi (线段树)
Problem Description Rikka and Yuta are interested in Phi function (which is known as Euler's totient function). Yuta gives Rikka an array  of positive integers, then Yuta makes  queries.   There are three types of queries:  Change  into ,
ShenduCC
2018/04/27
5900
P2068 统计和
题目描述 给定一个长度为n(n<=100000),初始值都为0的序列,x(x<=10000)次的修改某些位置上的数字,每次加上一个数,然后提出y (y<=10000)个问题,求每段区间的和。时间限制1秒。 输入输出格式 输入格式: 第一行1个数,表示序列的长度n 第二行1个数,表示操作的次数w 后面依次是w行,分别表示加入和询问操作 其中,加入用x表示,询问用y表示 x的格式为"x a b" 表示在序列a的位置加上b y的格式为"y a b" 表示询问a到b区间的加和 输出格式: 每行一个数,分别是每次询
attack
2018/04/12
6270
HDU 1556-差分数组和线段树的对比分析-Color the ball
差分数组 数据结构详解戳这里! 线段树 数据结构详解戳这里! 这两个数据结构的操作主要有两个:更新和查询。 假设数据结构总长度为n。 差分数组: 更新时间复杂度 O(1) 查询时间复杂度 O(n) 线段树 : 更新时间复杂度 O(logn) 查询时间复杂度 O(logn) 因此,差分数组适用于多次更新,常量次查询,数据范围在1e7以内的情况;线段树适用于多次更新,多次查询,数据范围在1e5以内的情况。 下面例题的要求比较低,两种数据结构都可以用。如果改动一下要求: 1、数据范围不是1e5而是1e7,只能用差分数组。 2、不是一次查询而是多次查询,只能用线段树。
全栈程序员站长
2022/08/23
2670
HDU 2665 Kth number(可持续化线段树)
Kth number Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 9213    Accepted Submission(s): 2868 Problem Description Give you a sequence and ask you the kth big number of a inteval. Input The f
ShenduCC
2018/04/27
4590
2019 HDU 多校赛第三场 HDU 6609 Find the answer(树状数组+二分答案 查询前k小)
题意: 多组询问,n个人,值m, 接下来n个值,要求当前值加上前面尽量多的值之和小于等于 m ,问前面要去掉几个值
用户2965768
2019/08/01
4360
HDU4027
本以为对线段树还是比较熟悉的,但是这题改变了我的想法。 顺着wk的题解做了这题。 拿到手就知道线段树,写完T,这时候我想起来蓝桥杯的线段树也是这样的吧,只不过那题对区间的操作是log,真可笑,当时还以为是cin写跪了,就这题看来,估计也那题没过几组数据,二等奖也在情理之中。 每次都更新到最底下会超时,每个数sqrt几次之后就会成为1,这时再开方是没有意义的,可以剪枝,如果区间长度等于区间和,说明区间没有必要更新,可以直接return。 此外还有好几个WA点 #include<cstdio> #include
triplebee
2018/01/12
5810
【算法】整体二分初探[通俗易懂]
大家好,我是架构君,一个会写代码吟诗的架构师。今天说一说【算法】整体二分初探,希望能够帮助大家进步!!!
Java架构师必看
2022/01/21
3390
HDU 5458 Stability(树链剖分+ 并查集)
2.如果删除(u, v)间的一条边可使其不连通,找出这样的边的个数,就是找(u, v)间桥的个数
用户2965768
2019/08/29
3580
HDU ACM 4578 Transformation-&gt;段树-间隔的变化
只有一个查询操作,这是要求[l,r]的数量之间p钍总和。并不是所有的查询所有节点,会议TLE。最好的是查询部件[a。b]。所有这个区间值我们是平等的,即能返回(b-a+1)*val 的值。区间内全部值都同样的情况的区间。对于置初值和加乘操作。分两种情况:1、当为置初值操作。直接覆盖区间就可以。并把标记的加乘操作赋为初始值。2、当为加乘操作时。先推断当前区间段是否为同样的值,是的话直接加乘,维护这个同样的值就可以。假设不同样,看区间是否已有加乘标记,把这个加乘标记一直传递下去。直到遇见那个区间段区间全部值同样时停止。最后把这个加乘赋给最開始的区间段。简单的说就是,覆盖操作可直接维护,不是覆盖操作的话。区间仅仅能保留一个加乘操作。
全栈程序员站长
2022/07/06
2450
2017.10.23解题报告
预计分数:100+60+0=160 实际分数:100+80+0=180 T1 题目描述 现在有一个字符串,每个字母出现的次数均为偶数。接下来我们把第一次出现的字母a和第二次出现的a连一条线,第三次出现的和四次出现的字母a连一条线,第五次出现的和六次出现的字母a连一条线...对其他25个字母也做同样的操作。 现在我们想知道有多少对连线交叉。交叉的定义为一个连线的端点在另外一个连线的内部,另外一个端点在外部。 下图是一个例子,共有三对连线交叉(我们连线的时候,只能从字符串上方经过)。 输入格式 一行一个字符串。
attack
2018/04/11
8640
牛客挑战赛49 D筱玛爱线段树 线段树+树状数组计数
 存下操作, 从后往前 用树状数组维护操作的次数, 编号从大到小,防止重复调用递归。
用户2965768
2019/07/08
3430
PKU A Simple Problem with Integers (段树更新间隔总和)
意甲冠军:一个典型的段树C,Q问题,有n的数量a[i] (1~n),C, a, b,c在[a,b]加c
全栈程序员站长
2022/07/06
1930
HDU 1394 Minimum Inversion Number (数据结构-段树)
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 9514 Accepted Submission(s): 5860
全栈程序员站长
2022/07/06
2080
HDU 5618 Jam's problem again(三维偏序,CDQ分治,树状数组,线段树)
Jam's problem again Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 640    Accepted Submission(s): 210 Problem Description Jam like to solve the problem which on the 3D-axis,given  points  If
ShenduCC
2018/04/27
1.1K0
Day3上午解题报告
预计分数:100+40+50=190 实际分数:100+40+50=190 T1 https://www.luogu.org/problem/show?pid=T15365 表示从来没做过博弈论的题,
attack
2018/04/11
7460
相关推荐
HDU 3333 Turing Tree (线段树)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验