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
26400
代码可运行
举报
运行总次数: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
5650
树套树专题——bzoj 3110: [Zjoi2013] K大数查询 &amp; 3236 [Ahoi2013] 作业 题解「建议收藏」
Time Limit: 20 Sec Memory Limit: 512 MB Submit: 978 Solved: 476
全栈程序员站长
2022/07/10
2490
HDU 5877 2016大连网络赛 Weak Pair(树状数组,线段树,动态开点,启发式合并,可持久化线段树)
Weak Pair Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others) Total Submission(s): 1468    Accepted Submission(s): 472 Problem Description You are given a  tree of  nodes, labeled from 1 to . To the th node a non-n
ShenduCC
2018/04/27
7330
模板模板模板模板模板模板模板模板模板模板模板模板模板模板模板模板模板模板模板模板
图论 最短路 SPFA 1 #include<cstdio> 2 #include<queue> 3 #include<cstring> 4 using namespace std; 5 c
attack
2018/04/12
33.7K0
【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
7700
PKU A Simple Problem with Integers (段树更新间隔总和)
意甲冠军:一个典型的段树C,Q问题,有n的数量a[i] (1~n),C, a, b,c在[a,b]加c
全栈程序员站长
2022/07/06
2000
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
6340
HDU 5458 Stability(树链剖分+ 并查集)
2.如果删除(u, v)间的一条边可使其不连通,找出这样的边的个数,就是找(u, v)间桥的个数
用户2965768
2019/08/29
3640
HDU 3450 Counting Sequences(线段树)
Counting Sequences Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/65536 K (Java/Others) Total Submission(s): 2335    Accepted Submission(s): 820 Problem Description For a set of sequences of integers{a1,a2,a3,...an}, we define a sequence
ShenduCC
2018/04/27
5340
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
7210
HDU 4605 Magic Ball Game(可持续化线段树,树状数组,离散化)
Magic Ball Game Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 2489    Accepted Submission(s): 759 Problem Description When the magic ball game turns up, Kimi immediately falls in it. The inter
ShenduCC
2018/04/27
6830
hdu4288 Coder(段树+分离)
就是直接申明一个vector的容器。然后直接用vector里面的操作比方 insert,erase等等操作。
全栈程序员站长
2022/07/05
2450
牛客挑战赛49 D筱玛爱线段树 线段树+树状数组计数
 存下操作, 从后往前 用树状数组维护操作的次数, 编号从大到小,防止重复调用递归。
用户2965768
2019/07/08
3490
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
4630
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
7890
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
5960
HDU ACM 4578 Transformation-&gt;段树-间隔的变化
只有一个查询操作,这是要求[l,r]的数量之间p钍总和。并不是所有的查询所有节点,会议TLE。最好的是查询部件[a。b]。所有这个区间值我们是平等的,即能返回(b-a+1)*val 的值。区间内全部值都同样的情况的区间。对于置初值和加乘操作。分两种情况:1、当为置初值操作。直接覆盖区间就可以。并把标记的加乘操作赋为初始值。2、当为加乘操作时。先推断当前区间段是否为同样的值,是的话直接加乘,维护这个同样的值就可以。假设不同样,看区间是否已有加乘标记,把这个加乘标记一直传递下去。直到遇见那个区间段区间全部值同样时停止。最后把这个加乘赋给最開始的区间段。简单的说就是,覆盖操作可直接维护,不是覆盖操作的话。区间仅仅能保留一个加乘操作。
全栈程序员站长
2022/07/06
2480
hdu 3966 树链剖分 点操作
/*by SilverN*/ #include<iostream> #include<algorithm> #include<cstring> #include<cstdio> #include<cmath> #define LL long long using namespace std; const int mxn=100010; int read() { int x=0,f=1; char ch=getchar(); while(ch<'0' || ch>'9') { if(ch=='-'
用户2965768
2019/08/29
3470
线段树维护矩阵乘法
Adding two numbers several times is a time-consuming task, so you want to build a robot. The robot should have a string of characters on its memory that represents addition instructions. Each character of the string, , is either or.
ACM算法日常
2019/11/25
7120
HDU 1556-差分数组和线段树的对比分析-Color the ball
差分数组 数据结构详解戳这里! 线段树 数据结构详解戳这里! 这两个数据结构的操作主要有两个:更新和查询。 假设数据结构总长度为n。 差分数组: 更新时间复杂度 O(1) 查询时间复杂度 O(n) 线段树 : 更新时间复杂度 O(logn) 查询时间复杂度 O(logn) 因此,差分数组适用于多次更新,常量次查询,数据范围在1e7以内的情况;线段树适用于多次更新,多次查询,数据范围在1e5以内的情况。 下面例题的要求比较低,两种数据结构都可以用。如果改动一下要求: 1、数据范围不是1e5而是1e7,只能用差分数组。 2、不是一次查询而是多次查询,只能用线段树。
全栈程序员站长
2022/08/23
2740
推荐阅读
相关推荐
HDU 3333 Turing Tree (线段树)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验