bzoj 2453: 维护队列

2453: 维护队列

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 1079  Solved: 503
[Submit][Status][Discuss]

Description

你小时候玩过弹珠吗?

小朋友A有一些弹珠,A喜欢把它们排成队列,从左到右编号为1到N。为了整个队列鲜艳美观,小朋友想知道某一段连续弹珠中,不同颜色的弹珠有多少。当然,A有时候会依据个人喜好,替换队列中某个弹珠的颜色。但是A还没有学过编程,且觉得头脑风暴太浪费脑力了,所以向你来寻求帮助。

Input

输入文件第一行包含两个整数N和M。

第二行N个整数,表示初始队列中弹珠的颜色。

接下来M行,每行的形式为“Q L R”或“R x c”,“Q L R”表示A想知道从队列第L个弹珠到第R个弹珠中,一共有多少不同颜色的弹珠,“R x c”表示A把x位置上的弹珠换成了c颜色。

Output

对于每个Q操作,输出一行表示询问结果。

Sample Input

2 3
1 2
Q 1 2
R 1 2
Q 1 2

Sample Output

2
1

HINT

对于100%的数据,有1 ≤ N ≤ 10000, 1 ≤ M ≤ 10000,小朋友A不会修改超过1000次,所有颜色均用1到10^6的整数表示。

Source

2011福建集训

带修莫队

#include<cmath>
#include<cstdio>
#include<algorithm>
#define N 10001
#define M 1000001
using namespace std;
int n,m,col[M],sum[M],ans[N];
int tot,now,siz,tmp;
struct     Query
{
    int l,r,bl,id,tim;
    bool operator <  (Query p) const
    {
        if(bl!=p.bl) return bl<p.bl;
        if(r!=p.r) return r<p.r;
        return tim<p.tim;
    }
}e[N];
struct Change
{
    int be,af,pos;
}g[1001];
void update(int p,int w)
{
    sum[p]+=w;
    if(sum[p]==1 && w==1) tmp++;
    if(!sum[p] && w==-1) tmp--;
}
int main()
{
    scanf("%d%d",&n,&m);
    siz=sqrt(n);
    for(int i=1;i<=n;i++) scanf("%d",&col[i]);
    char s[3]; int l,r;
    while(m--)
    {
        scanf("%s%d%d",s,&l,&r);
        if(s[0]==‘Q‘)
        {
            e[++tot].l=l; e[tot].r=r; e[tot].bl=(l-1)/siz; e[tot].tim=now;
            e[tot].id=tot;
        }
        else
        {
            g[++now].pos=l; g[now].af=r;
        }
    }
    sort(e+1,e+tot+1);
    int L=1,R=0; now=0;
    for(int i=1;i<=tot;i++)
    {
        while(now<e[i].tim)
        {
            now++;
            g[now].be=col[g[now].pos];
            if(g[now].pos>=L&&g[now].pos<=R)
            {
                update(g[now].be,-1);
                update(g[now].af,1);
            }
            col[g[now].pos]=g[now].af;
        }
        while(now>e[i].tim)
        {
            if(g[now].pos>=L&&g[now].pos<=R)
            {
                update(g[now].af,-1);
                update(g[now].be,1);
            }
            col[g[now].pos]=g[now].be;
            now--;
        }
        while(e[i].l<L) update(col[--L],1);
        while(e[i].l>L) update(col[L++],-1);
        while(e[i].r>R) update(col[++R],1);
        while(e[i].r<R) update(col[R--],-1);
        ans[e[i].id]=tmp;
    }
    for(int i=1;i<=tot;i++) printf("%d\n",ans[i]);
}

优化后:

读入优化、1,-1改成 true,false

优化一半

#include<cmath>
#include<cstdio>
#include<algorithm>
#define N 10001
#define M 1000001
using namespace std;
int n,m,col[M],sum[M],ans[N];
int tot,now,siz,tmp;
struct     Query
{
    int l,r,bl,id,tim;
    bool operator <  (Query p) const
    {
        if(bl!=p.bl) return bl<p.bl;
        if(r!=p.r) return r<p.r;
        return tim<p.tim;
    }
}e[N];
struct Change
{
    int be,af,pos;
}g[1001];
void update(int p,bool w)
{
    if(w)
    {
        sum[p]++;
        if(sum[p]==1) tmp++;
    }
    else
    {
        sum[p]--;
        if(!sum[p]) tmp--;
    }
}
void read(int &x)
{
    x=0; char c=getchar();
    while(c<‘0‘||c>‘9‘) c=getchar();
    while(c>=‘0‘&&c<=‘9‘) { x=x*10+c-‘0‘; c=getchar(); }
}
int main()
{
    read(n); read(m);
    siz=sqrt(n);
    for(int i=1;i<=n;i++) read(col[i]);
    char s[3]; int l,r;
    while(m--)
    {
        scanf("%s",s);
        read(l); read(r);
        if(s[0]==‘Q‘)
        {
            e[++tot].l=l; e[tot].r=r; e[tot].bl=(l-1)/siz; e[tot].tim=now;
            e[tot].id=tot;
        }
        else
        {
            g[++now].pos=l; g[now].af=r;
        }
    }
    sort(e+1,e+tot+1);
    int L=1,R=0; now=0;
    for(int i=1;i<=tot;i++)
    {
        while(now<e[i].tim)
        {
            now++;
            g[now].be=col[g[now].pos];
            if(g[now].pos>=L&&g[now].pos<=R)
            {
                update(g[now].be,false);
                update(g[now].af,true);
            }
            col[g[now].pos]=g[now].af;
        }
        while(now>e[i].tim)
        {
            if(g[now].pos>=L&&g[now].pos<=R)
            {
                update(g[now].af,false);
                update(g[now].be,true);
            }
            col[g[now].pos]=g[now].be;
            now--;
        }
        while(e[i].l<L) update(col[--L],true);
        while(e[i].l>L) update(col[L++],false);
        while(e[i].r>R) update(col[++R],true);
        while(e[i].r<R) update(col[R--],false);
        ans[e[i].id]=tmp;
    }
    for(int i=1;i<=tot;i++) printf("%d\n",ans[i]);
}
时间: 2024-10-03 23:00:36

bzoj 2453: 维护队列的相关文章

bzoj 2453 : 维护队列 带修莫队

2453: 维护队列 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 952  Solved: 432[Submit][Status][Discuss] Description 你小时候玩过弹珠吗? 小朋友A有一些弹珠,A喜欢把它们排成队列,从左到右编号为1到N.为了整个队列鲜艳美观,小朋友想知道某一段连续弹珠中,不同颜色的弹珠有多少.当然,A有时候会依据个人喜好,替换队列中某个弹珠的颜色.但是A还没有学过编程,且觉得头脑风暴太浪费脑力了,所以向你

Bzoj 2453: 维护队列 &amp;&amp; Bzoj 2120: 数颜色 分块,bitset

2453: 维护队列 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 578  Solved: 247[Submit][Status][Discuss] Description 你小时候玩过弹珠吗? 小朋友A有一些弹珠,A喜欢把它们排成队列,从左到右编号为1到N.为了整个队列鲜艳美观,小朋友想知道某一段连续弹珠中,不同颜色的弹珠有多少.当然,A有时候会依据个人喜好,替换队列中某个弹珠的颜色.但是A还没有学过编程,且觉得头脑风暴太浪费脑力了,所以向你

BZOJ.2453.维护队列([模板]带修改莫队)

题目链接 带修改莫队: 普通莫队的扩展,依旧从[l,r,t]怎么转移到[l+1,r,t],[l,r+1,t],[l,r,t+1]去考虑 对于当前所在的区间维护一个vis[l~r]=1,在修改值时根据是否在当前区间内修改即可. 块大小取\(O(n^{\frac{2}{3}})\),排序依次按左端点所在块.右端点所在块.修改次数(时间) 复杂度为\(O(n^{\frac{5}{3}})\) (证明在这) #include <cmath> #include <cstdio> #inclu

BZOJ 2120 数颜色&amp;2453 维护队列 [带修改的莫队算法]【学习笔记】

题意: 询问区间中不同颜色的个数,单点修改颜色 发现以前写的学习笔记没法看,于是重写一下(不就是会用latex了嘛) 额外维护一个当前修改操作执行到的时间 如果要进行某个查询操作,修改操作的时间必须移动到这个查询操作处 按照$(pos[l], pos[r], tim)$排序 令$S=N^{\frac{2}{3}}$, 有$N^{\frac{1}{3}}$块 $l$移动$N*N^{\frac{2}{3}}$次 $r$移动$N*N^{\frac{1}{3}}+N*N^{\frac{2}{3}}$次

【BZOJ】2453: 维护队列&amp;&amp;【BZOJ】2120: 数颜色 二分+分块 双倍经验

Description 你小时候玩过弹珠吗? 小朋友A有一些弹珠,A喜欢把它们排成队列,从左到右编号为1到N.为了整个队列鲜艳美观,小朋友想知道某一段连续弹珠中,不同颜色的弹珠有多少.当然,A有时候会依据个人喜好,替换队列中某个弹珠的颜色.但是A还没有学过编程,且觉得头脑风暴太浪费脑力了,所以向你来寻求帮助. Input 输入文件第一行包含两个整数N和M. 第二行N个整数,表示初始队列中弹珠的颜色. 接下来M行,每行的形式为“Q L R”或“R x c”,“Q L R”表示A想知道从队列第L个弹

BZOJ2453: 维护队列

2453: 维护队列 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 183  Solved: 89[Submit][Status] Description 你小时候玩过弹珠吗? 小朋友A有一些弹珠,A喜欢把它们排成队列,从左到右编号为1到N.为了整个队列鲜艳美观,小朋友想知道某一段连续弹珠中,不同颜色的弹珠有多少.当然,A有时候会依据个人喜好,替换队列中某个弹珠的颜色.但是A还没有学过编程,且觉得头脑风暴太浪费脑力了,所以向你来寻求帮助. Inp

[bzoj2453]维护队列_带修改莫队

维护队列 bzoj-2453 题目大意:给定一个n个数序列,支持查询区间数的种类数,单点修改.不强制在线. 注释:$1\le n,m\le 10^5$. 想法: 带修改莫队裸题. 如果没有修改操作的话,我们就正常按照莫队一样左右移动区间即可. 有了修改操作的话,我们把块变成$n^{\frac{2}{3}}$,关键字变成:左端点所在块.右端点所在块和时间戳. 然后暴力就行了. Code: #include <iostream> #include <cstdio> #include &

【数据结构】维护队列

T69293 维护队列 题目描述 Alice 给 Bob 布置了很多工作,他忙的不可开交,决定按照“先进先出(FIFO)”的顺序依次处理这些工作.但是处理过程中,Bob 意识到这种顺序可能不是最优的,因此他会选择性的把某些工作延后. 抽象来说,你需要维护一个队列,支持三种操作: 操作一:1 v,在队尾加入一个价值为 v 的任务. 操作二:2,如果当前队列为空,输出 -1:否则输出队头任务的价值,并将队头弹出. 操作三:3,如果当前队列为空,则不进行任何操作:否则将队列中价值最小的任务挪到队尾,保

BZOJ2453维护队列&amp;&amp;BZOJ2120数颜色

2016-05-28 11:20:22 共同的思路:维护某种颜色上一次在哪里出现 BZOJ2453 http://www.lydsy.com/JudgeOnline/problem.php?id=2453 BZOJ2120 http://www.lydsy.com/JudgeOnline/problem.php?id=2120 #include<bits/stdc++.h> #define inf 1000000000 #define ll long long #define N 10005