首页 > 其他分享 >SS241113C. 数据结构 (struct)

SS241113C. 数据结构 (struct)

时间:2024-11-13 21:19:05浏览次数:1  
标签:le struct int mn pos ch SS241113C 数据结构 mx

SS241113C. 数据结构 (struct)

题意

有 \(n\) 个数,\(m\) 个操作,\(n,m,a_i\le 10^6\),每次操作给区间 \([l,r]\) 的所有数字加 \(1\),然后输出全局颜色数量,操作独立

思路

感觉不好想,对我来讲有点难,需要更聪明的脑袋和丰富的想象力。

首先 \(O(n \sqrt{n})\) 的莫队做法是显然的,假设 \(n,m\) 同阶。

考虑从操作出发,操作比较特别,是区间 \(+1\)。

那么对于区间每个颜色 \(c\),都会变成 \(c+1\)。此时需要分 \(c\) 是否消失,\(c+1\) 是否新出现讨论。

  1. \(c\) 消失了。

说明所有 \(c\) 都在 \([l,r]\) 内,设 \(mn_c,mx_c\) 分别为 \(c\) 最小、最大出现的位置,即 \(l \le mn_c \le mx_c \le r\)。

这个可以扫描线二维数点做,扫描 \(mx_c,r\),数 \(l,mn_c\)。

  1. \(c+1\) 新出现了。

计算这个贡献的前提是 \([l,r]\) 中存在 \(c\)。

注意因为我们会讨论 \(c+1\) 消失了的情况,并且会计入贡献,因此这里其实是计算在 \([l,r]\) 之外没有 \(c+1\)。如果存在颜色 \(c+1\),则要求 \(l \le mn_{c+1} \le mx_{c+1} \le r\),这个和刚刚一样。另一种情况是本来就不存在颜色 \(c+1\)。

简化一下。发现如果操作区间存在 \(c\),且满足 \(c+1\) 全部在操作区间里面,那么原来的 \(c+1\) 就会消失,然后又会有新的 \(c+1\) 出现,因此无需考虑这种情况。而如果本来不存在 \(c+1\),那么也不会有 \(c+1\) 消失的情况。

因此我们要考虑的是:

  1. 操作区间里面没有 \(c\),而 \(c+1\) 全部在操作区间里面,答案减一。
  2. 操作区间里面有 \(c\),而本来不存在 \(c+1\),答案加一。

\([l,r]\) 中不存在 \(c\)。也就是 \([l,r] \subseteq\) 某两个相邻的颜色 \(c\) 之间。

即 \(pos_l < l \le mn_{c+1} \le mx_{c+1} \le r < pos_r\)。其中 \(pos_l,pos_r\) 表示相邻的两个 \(c\) 的位置。

下面是难点。

扫描 \(r\),扫到 \(mx_{c+1}\) 的时候,在树状数组的 \((pos_l,mn_{c+1}]\) 的位置减 \(1\)(注意区间可能为空集)。扫到 \(pos_r\) 的时候,如果 \(mx_{c+1} \le pos_r\)(注意可以取等,因为等于的时候你之间是减过贡献的,需要加回去),在树状数组的 \((pos_l,mn_{c+1}]\) 的位置加回 \(1\)(注意此时不一定存在 \(c+1\))。

然后你发现操作 \(2\),其实就是当不存在 \(c+1\) 的时候,此时你刚好扫到 \(pos_r\),直接给 \((pos_l,pos_r]\) 加一!

时间复杂度 \(O((n+m) \log n)\)。感觉理解难度比较大。

code

#include<bits/stdc++.h>
#define sf scanf
#define pf printf
#define rep(x,y,z) for(int x=y;x<=z;x++)
#define per(x,y,z) for(int x=y;x>=z;x--)
using namespace std;
typedef long long ll;
namespace poetry {
    #define isdigit(x) (x>='0'&&x<='9')
    #define gc getchar_unlocked
    #define pc putchar_unlocked
    template <typename T>
    void read(T &x) {
        x=0;
        char ch=gc();
        for(;!isdigit(ch);ch=gc());
        for(;isdigit(ch);ch=gc()) x=(x<<3)+(x<<1)+(ch^48);
    }
    template <typename T>
    void write(T x,char ch) {
        static int st[40];
        int top=0;
        do {
            st[top++]=x%10;
            x/=10;
        }while(x);
        while(top) pc(st[--top]^48);
        pc(ch);
    }
    constexpr int N=1e6+7;
    int n,m;
    int a[N];
    int tr[N];
    int ans[N];
    void add(int x,int val) { for(;x<=n;x+=x&-x) tr[x]+=val; }
    int query(int x) {
        int s=0;
        for(;x;x-=x&-x) s+=tr[x];
        return s;
    }
    struct que {
        int id,l,r;
    }q[N];
    bool cmp (que a,que b) { return a.r < b.r; }
    int mx[N],mn[N],mx_pos[N],my_pos[N];
    int sum;
    void main() {
        read(n),read(m);
        rep(i,1,n) read(a[i]);
        rep(i,1,m) read(q[i].l),read(q[i].r),q[i].id=i;
        rep(i,1,n+1) mn[i]=n+1;
        per(i,n,1) mn[a[i]]=i;
        rep(i,1,n) my_pos[i]=mx[a[i]], mx_pos[a[i]]=mx[a[i]-1], mx[a[i]]=i;
        rep(i,1,n) if(mx[i]) sum++;
        sort(q+1,q+m+1,cmp);
        int it=0;
        rep(i,1,m) {
            int l=q[i].l,r=q[i].r;
            while(it<r) {
                ++it;
                if(it==mx[a[it]]) {
                    int L=mx_pos[a[it]], R=mn[a[it]];
                    if(L<R) add(L+1,-1), add(R+1,1);
                }
                if(it>=mx[a[it]+1]) {
                    int L=my_pos[it], R=min(it,mn[a[it]+1]);
                    if(L<R) add(L+1,1), add(R+1,-1);
                }
            }
            ans[q[i].id]=query(l);
        }
        rep(i,1,m) write(sum+ans[i],'\n');
    }
}
int main() {
    #ifdef LOCAL
    freopen("my.out","w",stdout);
    #else 
    freopen("struct.in","r",stdin);
    freopen("struct.out","w",stdout);
    #endif
    poetry :: main();
}

标签:le,struct,int,mn,pos,ch,SS241113C,数据结构,mx
From: https://www.cnblogs.com/liyixin0514/p/18544758

相关文章

  • 数据结构——串的顺序存储实现
    概念:串(string):零个或多个任意字符组成的有限序列空串:(与空集合符号相同)子串:串中任意个连续字符组成的子序列称为该串的子串主串:包含子串的串相应地称为主串字符位置:字符在序列中的序号为该字符在串中的位置子串位置:子串第一个字符在主串中的位置空格串:由一个或多个空格组......
  • 【新人系列】Python 入门(九):数据结构 - 中
    ✍个人博客:https://blog.csdn.net/Newin2020?type=blog......
  • 单链表算法题(数据结构)
    1.反转链表https://leetcode.cn/problems/reverse-linked-list/description/题目:看到这个题目的时候我们怎么去想呢?如果我们反应快的话,应该可以想到我们可以从1遍历到5然后依次头插,但是其实我们还有更好的办法,就是利用三个指针,如何使用呢?反转链表OJ假如结构体已经给出t......
  • 数据结构复习——链、链栈。
    1、栈(Stack):是只允许在一端进行插入或删除的线性表。首先栈是一种线性表,但限定这种线性表只能在某一端进行插入和删除操作。2、栈的常见基本操作:InitStack(&S):初始化一个空栈S。StackEmpty(S):判断一个栈是否为空,若栈为空则返回true,否则返回false。Push(&S,x):进栈(栈的插入操作),若栈......
  • 基础数据结构【c语言版】之 “图” 详细讲述
    别忘了请点个赞+收藏+关注支持一下博主喵!!!1. 图的定义和术语1.1图的定义**图(Graph)**是由顶点(Vertex)和边(Edge)组成的一个集合,可以表示顶点之间的关系。通常,图可以表示为G=(V,E)G=(V,E)G=(V,E),其中:VVV是顶点集合,表示图中的所有顶点。EEE是边集合,表示图中顶点之间的连接......
  • 如何正确导入mapstruct,同时避免编译时mapstruct与lombok冲突
    本文介绍编译时产生的冲突,导包时期产生的冲突请劳驾查找其他解决方法一般情况下只需要按照官网的导入即可,但如果同时使用了lombok,则需要小心。详细信息可以查看官网文档:MapStruct1.5.5.Final集成lombok注意:在编译测试的时候,一定先清理再编译。这样可以解决80%的报错问题......
  • 【初阶数据结构与算法】线性表之链表的分类以及双链表的定义与实现
    文章目录一、链表的分类二、双链表的实现1.双链表结构的定义2.双链表的初始化和销毁初始化函数1初始化函数2销毁函数3.双链表的打印以及节点的申请打印函数节点的申请4.双链表的头插和尾插头插函数尾插函数5.双链表的查找和判空查找函数判空函数6.双链表的头删和尾......
  • 数据结构——快速排序
    目录一、排序思想二、代码实现(一)hoare版1、原版——固定选key2、随机选key、三数取中选key(二)挖坑法(三)前后指针法(四)小区间优化(五)非递归写法一、排序思想任取待排序元素序列中的某元素作为基准值,按照该基准值将待排序集合分割成两子序列,左子序列中所有元素均小于基......
  • C++数据结构实验题目解析
    目录题目:考点分析:难点1:就地逆置步骤:代码实现:核心代码详细解释:难点2:①非递减链表,②删除相同元素代码详解①:代码详解②:完整代码:大家好,今天我就来给大家分析一下我上期分享的题目的详细解析,编程的能力都是逐步提升的,但是思维的锻炼可以提前进行,这样有助于我们以后自......
  • 郝玩的数据结构1——单调栈,单调队列
    栈和队列是很郝咏的Stl,那么,我们手搓——用数组模拟故事背景:辣鸡老o在学单调栈&单调队列——我栈top为栈顶,易得出出栈即top--,入栈++top=(ovo)......——完全不会讲,那么上马:点击查看代码#include<bits/stdc++.h>usingnamespacestd;constintN=114514;intstk[N],top=0;......