关闭

支(zi)持(ci)修改的莫队算法

标签: OI莫队算法
2441人阅读 评论(5) 收藏 举报
分类:

Preface

相信大家对O(n32)离线解决序列问题莫队算法都不陌生,在这里我要介绍一下能够兹瓷修改操作的莫队算法。


Basis

关于基本的不带修改的莫队算法,参考cty的博客:http://blog.csdn.net/alan_cty/article/details/51277499


Algorithm

分块大小Sn23,那么我们就有n13块。
原本的莫队关键字只有两个,一个是左边界,一个是右边界。而带修改莫队要再加上一维:在第几个操作之后。
我们按照这左边界所在块、右边界所在块以及第三关键字排序(上面说的那个)。
统计答案时多维护一个指针记录修改操作执行到哪里,移动时直接修改即可,如果在区间内还要计算其对答案的影响。
左指针移动次数:O(n×n23)=O(n53)
右指针移动次数:O(n×n23+n13×n)=O(n53)
修改指针移动:O((n13)2×n)=O(n53)
因此总时间复杂度O(n53)


代码实现

题目来源[JZOJ2491]维护队列。带修改莫队裸题。

#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cctype>

using namespace std;

int read()
{
    int x=0,f=1;
    char ch=getchar();
    while (!isdigit(ch)) ch=='-'?f=-1:f,ch=getchar();
    while (isdigit(ch)) x=x*10+ch-'0',ch=getchar();
    return x*f;
}

const int N=10005;
const int M=10005;
const int C=1000005;
const int B=250;

struct Q
{
    int l,r,t,id;
}query[M];

bool operator<(Q x,Q y){return (x.l-1)/B<(y.l-1)/B||(x.l-1)/B==(y.l-1)/B&&(((x.r-1)/B<(y.r-1)/B)||(x.r-1)/B==(y.r-1)/B&&x.t<y.t);}

struct E
{
    int x,c0,c1;
}modify[M];

int color[N],ct[N];
int n,m,qs,es,now;
int ans[M];
int cnt[C];

void add(int x){now+=!(cnt[color[x]]++);}

void erase(int x){now-=!(--cnt[color[x]]);}

void change(int x,int l,int r,bool tp)
{
    int y=modify[x].x;
    if (l<=y&&y<=r) erase(y);
    color[y]=tp?modify[x].c1:modify[x].c0;
    if (l<=y&&y<=r) add(y);
}

void Motao()
{
    now=0;
    int lcur=query[1].l,rcur=query[1].r,mcur=query[1].t;
    for (int i=lcur;i<=rcur;i++) add(i);
    for (int i=1;i<=mcur;i++) change(i,lcur,rcur,1);
    ans[query[1].id]=now;
    for (int i=2;i<=qs;i++)
    {
        while (lcur<query[i].l) erase(lcur++);
        while (query[i].l<lcur) add(--lcur);
        while (query[i].r<rcur) erase(rcur--);
        while (rcur<query[i].r) add(++rcur);
        while (mcur<query[i].t) change(++mcur,lcur,rcur,1);
        while (query[i].t<mcur) change(mcur--,lcur,rcur,0);
        ans[query[i].id]=now;
    }
}

int main()
{
    freopen("maintain.in","r",stdin),freopen("maintain.out","w",stdout);
    n=read(),m=read(),qs=es=0;
    for (int i=1;i<=n;i++) ct[i]=color[i]=read();
    for (int i=1,u,v;i<=m;i++)
    {
        char cmd=getchar();
        while (cmd!='Q'&&cmd!='R') cmd=getchar();
        u=read(),v=read();
        if (cmd=='Q') query[++qs].l=u,query[qs].r=v,query[qs].t=es,query[qs].id=qs;
        else modify[++es].x=u,modify[es].c0=color[u],color[u]=modify[es].c1=v;
    }
    for (int i=1;i<=n;i++) color[i]=ct[i];
    sort(query+1,query+1+qs);
    Motao();
    for (int i=1;i<=qs;i++) printf("%d\n",ans[i]);
    fclose(stdin),fclose(stdout);
    return 0;
}
2
0
查看评论
发表评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场

带修改的莫队算法学习小记

简介莫涛大神创造出的离线询问算法的带修改版。 算法基础:需要掌握莫队算法,会打暴搜(暴力)。 一个叫莫的双端队列。 只支持单点修改操作方法普通的不带修改的莫队算法要把每个询问带上两个关键字排序,...
  • doyouseeman
  • doyouseeman
  • 2016-07-10 09:15
  • 3038

bzoj 2120: 数颜色(带修改的莫队算法)

2120: 数颜色 Time Limit: 6 Sec  Memory Limit: 259 MB Submit: 2908  Solved: 1130 [Submit][Status][Dis...
  • clover_hxy
  • clover_hxy
  • 2016-05-09 21:47
  • 2308

莫队(支持修改)算法

莫队算法是个很好玩的东西,代码复杂度直降! 莫队算法可以适应一些可以从i直接转移到(i+1)的题目的离线算法,莫队算法把每个询问看成再二维平面上的点, 要使我暴力执行的次数尽量的少,顺序肯定是二维曼...
  • HOWARLI
  • HOWARLI
  • 2016-07-13 21:51
  • 438

【模板】带修改莫队 (模板题:洛谷P1903数颜色)

带修改莫队讲解 ~阅前提示: 拥有普通莫队的基础知识;理解莫队的思想; ~简介: 莫队支持的是离线操作,普通莫队只支持查询操作; 而带修改莫队还支持单点修改操作。 ~原理: 普通莫队每一个...
  • zj_yuneng
  • zj_yuneng
  • 2017-05-25 18:38
  • 315

莫队算法——解决序列上询问的利器 (2) 带修改的莫队

普通的莫队戳这里。   还是考虑类似的问题:有一个长为N序列,有M个操作:1.询问:在区间[L,R]内,出现了多少个不同的数字。2.修改,将第x个数改为v(序列中所有数字均小于K)。题目会给出K。 ...
  • WT_cnyali
  • WT_cnyali
  • 2017-03-28 22:04
  • 255

Dynamic len 题解+代码 (带修改莫队算法模板)

Description有n个数编号从0→n-1,两种操作: Q L R:询问编号为L→R-1的数中共有多少种不同的数 M X Y:将编号为X的数改为Y 共有m个操作Input第一行两个数n,m ...
  • u011056504
  • u011056504
  • 2016-07-08 21:57
  • 884

bzoj 4129: Haruna’s Breakfast (带修改树上莫队+分块)

4129: Haruna’s Breakfast Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 589  Solved: 313 [Submi...
  • clover_hxy
  • clover_hxy
  • 2017-03-05 20:52
  • 208

树上(带修改)莫队算法-- bzoj4129 && bzoj3757

bzoj3757似乎因为版权挂了 首先,我们要熟悉序列莫队 然后考虑树上莫队 我们用(l,r)表示当前l到r这条链上的答案(不包括lca),现在考虑从(l,r)转移到(L,R)我们用(l,r)表...
  • lcrtest
  • lcrtest
  • 2016-07-10 12:52
  • 617

[BZOJ2120]数颜色(带修改莫队)

题目描述传送门题解和BZOJ2453相同,在这里可以看到分块的做法 而这道题同时又是一道带修莫队裸题 带修莫队大体方法如下: 1、将修改询问离线并分开,记录每一个修改之前最近的一次询问的编号 ...
  • Clove_unique
  • Clove_unique
  • 2017-03-06 22:40
  • 344

莫队算法

这名字···这个算法是由之前的国家队队长莫涛巨神(Orz….%%%64^{64})发明的,所以尊称莫队算法。啊?莫队算法是什么?我不会!事实上,莫队算法这种东西,应该叫做——一个优雅的暴力(引自Ala...
  • hzj1054689699
  • hzj1054689699
  • 2016-07-09 16:24
  • 7557
    个人资料
    • 访问:129811次
    • 积分:3739
    • 等级:
    • 排名:第9981名
    • 原创:228篇
    • 转载:0篇
    • 译文:0篇
    • 评论:60条
    博客专栏
    OI

    文章:14篇

    阅读:16917
    最新评论
    文章分类