zoukankan      html  css  js  c++  java
  • 【BZOJ 2453|bzoj 2120】 2453: 维护队列 (分块+二分)

    2453: 维护队列

    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

    【分析】

      跟BZOJ 3343 差不多。

      对序列求一个next,next[i]表示下一个和i同颜色的是谁(如果他是最后一个的这种颜色,那么next为正无穷)

      问题转换成计算区间[l,r]里面next大于r的有多少个,单点修改。

      转化成跟BZOJ 3343 一样的模型。

      根号n分块,块内要排序。next这条链的删除和插入可以暴力枚举,因为数据范围很小。

      时间复杂度是O(q*√n log(√n)+q*n)

      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<cstring>
      4 #include<iostream>
      5 #include<algorithm>
      6 #include<cmath>
      7 using namespace std;
      8 #define Maxn 10010
      9 #define Maxd 1000010
     10 
     11 int a[Maxn],pos[Maxn],ft[Maxn],rt[Maxn];
     12 int nt[Maxn],lt[Maxd],b[Maxn];
     13 int n;
     14 
     15 bool cmp(int x,int y) {return x>y;}
     16 
     17 void upd(int x)
     18 {
     19     for(int i=ft[x];i<=rt[x];i++) b[i]=nt[i];
     20     sort(b+ft[x],b+1+rt[x],cmp);
     21 }
     22 
     23 void change(int x,int y)
     24 {
     25     if(lt[a[x]]==x)
     26     {
     27         lt[a[x]]=nt[x];
     28     }
     29     else
     30     {
     31         for(int i=lt[a[x]];i<=n;i=nt[i]) if(nt[i]==x)
     32         {
     33             nt[i]=nt[x];
     34             upd(pos[i]);
     35             break;
     36         }
     37     }
     38     if(x<lt[y])
     39     {
     40         nt[x]=lt[y];
     41         lt[y]=x;
     42     }
     43     else
     44     {
     45         for(int i=lt[y];i<=n;i=nt[i]) if(nt[i]>x)
     46         {
     47             nt[x]=nt[i];
     48             nt[i]=x;
     49             upd(pos[i]);
     50             break;
     51         }
     52     }
     53     upd(pos[x]);
     54     a[x]=y;
     55 }
     56 
     57 int ffind(int x,int y)
     58 {
     59     int l=ft[x],r=rt[x];
     60     if(b[l]<y) return 0;
     61     while(l<r)
     62     {
     63         int mid=(l+r+1)>>1;
     64         if(b[mid]>y) l=mid;
     65         else r=mid-1;
     66     }
     67     return l-ft[x]+1;
     68 }
     69 
     70 int query(int x,int y)
     71 {
     72     int ans=0;
     73     if(pos[x]==pos[y])
     74     {
     75         for(int i=x;i<=y;i++) if(nt[i]>y) ans++;
     76     }
     77     else
     78     {
     79         for(int i=x;i<=rt[pos[x]];i++) if(nt[i]>y) ans++;
     80         for(int i=ft[pos[y]];i<=y;i++) if(nt[i]>y) ans++;
     81         for(int i=pos[x]+1;i<pos[y];i++) ans+=ffind(i,y);
     82     }
     83     return ans;
     84 }
     85 
     86 int main()
     87 {
     88     int m,sq;
     89     scanf("%d%d",&n,&m);
     90     sq=(int)ceil(sqrt((double)n));
     91     for(int i=1;i<=n;i++) scanf("%d",&a[i]);
     92     for(int i=1;i<=Maxd;i++) lt[i]=n+1;
     93     for(int i=n;i>=1;i--) nt[i]=lt[a[i]],lt[a[i]]=i;
     94     for(int i=1;i<=n;i++) pos[i]=(i-1)/sq+1;
     95     for(int i=1;i<n;i++) if(pos[i]!=pos[i+1]) ft[pos[i+1]]=i+1,rt[pos[i]]=i;
     96     ft[1]=1;rt[pos[n]]=n;
     97     for(int i=1;i<=n;i++) b[i]=nt[i];
     98     for(int i=1;i<=pos[n];i++) sort(b+ft[i],b+1+rt[i],cmp);
     99     
    100     for(int i=1;i<=m;i++)
    101     {
    102         char s[10];
    103         int x,y;
    104         scanf("%s%d%d",s,&x,&y);
    105         if(s[0]=='R')
    106         {
    107             change(x,y);
    108         }
    109         else
    110         {
    111             printf("%d
    ",query(x,y));
    112         }
    113     }
    114     return 0;
    115 }
    View Code

    2016-12-12 13:52:29

  • 相关阅读:
    deepin-wine-tim 字体发虚
    windows&linux双系统时间相差8小时
    Linux 禁用 ipv6
    双系统win10更新后无法进入linux
    Failed to receive SOCKS4 connect request ack 解决
    zsh 使用通配符功能
    vux修改css样式的2种办法
    Ubuntu 16.04 安装OpenSSH7.4
    Nginx开启http2访问和gzip网页压缩功能
    vue开发环境和生产环境里面解决跨域的几种方法
  • 原文地址:https://www.cnblogs.com/Konjakmoyu/p/6164176.html
Copyright © 2011-2022 走看看