• BZOJ2453: 维护队列


    2453: 维护队列

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 183  Solved: 89
    [Submit][Status]

    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

    题解:

    用pre[i]记录前一个和i相同颜色的球的所在位置

    询问l到r时,如果pre[i]<r说明在l到i这一段没用和i颜色相同的球,则ans++

    利用这种思路我们可以。。。分块

    每一块内按pre[i]排序,然后和教主的魔法那题都一样了

    -----hzwer

    代码:

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cmath>
     4 #include<cstring>
     5 #include<algorithm>
     6 #include<iostream>
     7 #include<vector>
     8 #include<map>
     9 #include<set>
    10 #include<queue>
    11 #include<string>
    12 #define inf 1000000000
    13 #define maxn 10000+1000
    14 #define maxm 1000000+1000
    15 #define eps 1e-10
    16 #define ll long long
    17 #define pa pair<int,int>
    18 using namespace std;
    19 inline int read()
    20 {
    21     int x=0,f=1;char ch=getchar();
    22     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    23     while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
    24     return x*f;
    25 }
    26 int n,m,block,b[maxn],c[maxn],pre[maxn],pos[maxn],last[maxm];
    27 void reset(int x)
    28 {
    29     int l=(x-1)*block+1,r=min(x*block,n);
    30     for(int i=l;i<=r;i++)pre[i]=b[i];
    31     sort(pre+l,pre+r+1);
    32 }
    33 int find(int x,int y)
    34 {
    35     int l=(x-1)*block+1,r=x*block,mid;
    36     while(l<=r)
    37     {
    38         mid=(l+r)>>1;
    39         if(pre[mid]>=y)r=mid-1;else l=mid+1;
    40     }
    41     return l-(x-1)*block-1;
    42 }
    43 int query(int x,int y)
    44 {
    45     int sum=0,bx=pos[x],by=pos[y];
    46     if(by-bx<=1)
    47     {
    48         for(int i=x;i<=y;i++)if(b[i]<x)sum++;
    49     }
    50     else
    51     {
    52         for(int i=x;i<=bx*block;i++)if(b[i]<x)sum++;
    53         for(int i=(by-1)*block+1;i<=y;i++)if(b[i]<x)sum++;
    54     }
    55     for(int i=bx+1;i<by;i++)sum+=find(i,x);
    56     return sum;
    57 }
    58 void change(int x,int y)
    59 {
    60     for(int i=1;i<=n;i++)last[c[i]]=0;
    61     c[x]=y;
    62     for(int i=1;i<=n;i++)
    63     {
    64         int t=b[i];
    65         b[i]=last[c[i]];
    66         last[c[i]]=i;
    67         if(t!=b[i])reset(pos[i]);
    68     }
    69 }
    70 int main()
    71 {
    72     freopen("input.txt","r",stdin);
    73     freopen("output.txt","w",stdout);
    74     n=read();m=read();
    75     block=floor(sqrt(n));
    76     for(int i=1;i<=n;i++)
    77      {
    78          c[i]=read();
    79          pos[i]=(i-1)/block+1;
    80          b[i]=last[c[i]];
    81          last[c[i]]=i;
    82      }
    83     for(int i=1;i<=pos[n];i++)reset(i);
    84     char ch;int x,y;
    85     while(m--)
    86     {
    87         ch=' ';
    88         while(ch!='Q'&&ch!='R')ch=getchar();x=read();y=read();
    89         if(ch=='R')change(x,y);else printf("%d
    ",query(x,y));
    90     } 
    91     return 0;
    92 }
    View Code
  • 相关阅读:
    10-JS的函数学习
    Servlet(生命周期)
    09-js数组常用方法
    08-计算器案例
    07-js数组
    06-js的逻辑结构
    使用css设置三角形
    关于background-size 的一点小坑
    a 标签实现分享功能
    关于页面缩放时css错乱的处理方法---之一
  • 原文地址:https://www.cnblogs.com/zyfzyf/p/3945853.html
Copyright © 2020-2023  润新知