数颜色(带修莫队模板)

数颜色(luogu)

Description

题目描述

墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问。墨墨会向你发布如下指令:

1、 Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜色的画笔。

2、 R P Col 把第P支画笔替换为颜色Col。

为了满足墨墨的要求,你知道你需要干什么了吗?

输入格式

第1行两个整数N,M,分别代表初始画笔的数量以及墨墨会做的事情的个数。

第2行N个整数,分别代表初始画笔排中第i支画笔的颜色。

第3行到第2+M行,每行分别代表墨墨会做的一件事情,格式见题干部分。

输出格式

对于每一个Query的询问,你需要在对应的行中给出一个数字,代表第L支画笔到第R支画笔中共有几种不同颜色的画笔。

Solution

带修莫队模板(加一重排序元素:时间)

注意:每个时间点修改前 值可能不一样!!!卡了我一下午。。。

另外记得一定要吸氧

Code

#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
using namespace std;
const int N=1e6+10;
int n,m,T[N][3],a[N],nt,nl,nr,s[N],si,cnt,ans[N],an,tot;
char ch[5];
struct node
{
    int l,r,t,id;
    bool operator <(const node &o)const
    {
        return l/si==o.l/si?(r/si==o.r/si?t<o.t:r<o.r):l<o.l;
    }
}q[N];
void get(int x,int d)
{
    s[x]+=d;
    if(d<0) an-=s[x]==0;
    if(d>0) an+=s[x]==1;
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    for(int i=0;i<m;i++)
    {
        scanf("%s",ch);
        if(ch[0]==‘Q‘)
        {
            scanf("%d%d",&q[tot].l,&q[tot].r);
            q[tot].t=cnt,q[tot].id=tot,tot++;
        }
        else
        {
            ++cnt,scanf("%d%d",&T[cnt][0],&T[cnt][2]);
            T[cnt][1]=a[T[cnt][0]];
            a[T[cnt][0]]=T[cnt][2];
        }
    }
    for(int i=cnt;i;i--) a[T[i][0]]=T[i][1];
    si=ceil(exp((log(n)+log(cnt))/3));
    sort(q,q+tot);
    for(int i=0;i<tot;i++)
    {
        while(q[i].l<nl) an+=!s[a[--nl]]++;
        while(q[i].l>nl) an-=!--s[a[nl++]];
        while(q[i].r>nr) an+=!s[a[++nr]]++;
        while(q[i].r<nr) an-=!--s[a[nr--]];
        while(q[i].t<nt)
        {
            int wz=T[nt][0];
            if(nl<=wz && wz<=nr) an-=!--s[a[wz]];
            a[wz]=T[nt--][1];
            if(nl<=wz && wz<=nr) an+=!s[a[wz]]++;
        };
        while(q[i].t>nt)
        {
            int wz=T[++nt][0];
            if(nl<=wz && wz<=nr) an-=!--s[a[wz]];
            a[wz]=T[nt][2];
            if(nl<=wz && wz<=nr) an+=!s[a[wz]]++;
        };
        ans[q[i].id]=an;
    }
    for(int i=0;i<tot;i++)
        printf("%d\n",ans[i]);
    return 0;
}

原文地址:https://www.cnblogs.com/hsez-cyx/p/12260690.html

时间: 2024-08-29 20:19:10

数颜色(带修莫队模板)的相关文章

BZOJ2120数颜色(带修改莫队)

2120: 数颜色 Time Limit: 6 Sec  Memory Limit: 259 MBSubmit: 7384  Solved: 2998[Submit][Status][Discuss] Description 墨 墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问.墨墨会像你发布如下指令: 1. Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜色的画笔. 2. R P Col 把第P支画笔替换为颜色Col.为了满足墨墨的要求,你知道你需要

[国家集训队][bzoj2120] 数颜色 [带修改莫队]

题面: 传送门 思路: 这道题和SDOI2009的HH的项链很像,只是多了一个修改 模板套上去呀 莫队学习请戳这里:莫队 Code: 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 using namespace std; 7 inline int read(){ 8 int re=0,fla

2120: 数颜色(带修莫队)

题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=2120 2120: 数颜色 Time Limit: 6 Sec  Memory Limit: 259 MBSubmit: 10514  Solved: 4398[Submit][Status][Discuss] Description 墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问.墨墨会像你发布如下指令: 1. Q L R代表询问你从第L支画笔到第R

bzoj4129 Haruna’s Breakfast 树上带修莫队+分块

题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4129 题解 考虑没有修改的序列上的版本应该怎么做: 弱化的题目应该是这样的: 给定一个序列,每次询问区间 \([l, r]\) 中元素的最小没有出现的自然数. 这个弱化的版本可以用离线+线段树二分水掉.但是这个做法显然不太好搬到树上做. 上面的弱化版还有一个莫队做法:可以用莫队维护出来每一个区间的每一个数的出现为次数.把出现过的数通过分块表示出来,于是查询的时候枚举每一个块,寻找第一个不满的

【BZOJ-3052】糖果公园 树上带修莫队算法

3052: [wc2013]糖果公园 Time Limit: 200 Sec  Memory Limit: 512 MBSubmit: 883  Solved: 419[Submit][Status][Discuss] Description Input Output Sample Input Sample Output 84 131 27 84 HINT Source Solution 树上带修莫队 本质还是树上莫队,详情可以转 BZOJ-3757苹果树 但是这里需要修改,就需要一些特殊的地方

【带修莫队】【权值分块】bzoj3196 Tyvj 1730 二逼平衡树

这题用了三种算法写: 分块+二分:O(n*sqrt(n*log(n)) 函数式权值分块:O(n*sqrt(n)) 带修莫队+权值分块:O(n5/3) 结果……复杂度越高的实际上跑得越快……最后这个竟然进第一页了…… #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; int f,C; inline void R(int &

CF940F Machine Learning(带修莫队)

首先显然应该把数组离散化,然后发现是个带修莫队裸题,但是求mex比较讨厌,怎么办?其实可以这样求:记录每个数出现的次数,以及出现次数的出现次数.至于求mex,直接暴力扫最小的出现次数的出现次数为0的正整数,就一句话,这样看似会超时,实际上是O(√n)的复杂度.为什么?假设存在出现1,2,...,x的出现次数,则Σi(1<=i<=x)<=n,即x*(x+1)<=2*n,所以x至多是√n级别.很多人再把出现次数分块,根本没必要.然后考虑把数组分块的块大小,每次移动左指针,为O(n*块大

莫队 + 带修莫队

莫队其实就是一个带优化的暴力,通过将区间询问按一定规则进行排序,从而优化过程,求出答案. 举一例子:(例子不具备权威性,只是让读者了解莫队是干啥的) /* 输入四个区间 1 4 初始条件,L= R = 0, 将R遍历到4 需要走4步 L走一步,共5次 4 8 继承上一次 L 和 R 的值,L从1到4 需要3次,R从4到8,需4次, 总计8次 2 9 同理继承, L回退2次, R前进一次 总计3次 1 2 同理,L回退1次,R回退7次 总计8次 如果直接暴力,计算机将要计算 5+8+3+8=24次

[带修莫队] Bzoj 2120 数颜色

Description 墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问.墨墨会像你发布如下指令: 1. Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜色的画笔. 2. R P Col 把第P支画笔替换为颜色Col.为了满足墨墨的要求,你知道你需要干什么了吗? Input 第1行两个整数N,M,分别代表初始画笔的数量以及墨墨会做的事情的个数.第2行N个整数,分别代表初始画笔排中第i支画笔的颜色.第3行到第2+M行,每行分别代表墨墨会做的一件事情,格