zoukankan      html  css  js  c++  java
  • bzoj 2120 数颜色 (带修莫队)

    题目链接:

    https://www.lydsy.com/JudgeOnline/problem.php?id=2120

    题意:两种操作:Q 询问区间  l - r  内颜色的种类 ,R 单点修改

    思路:

    带修莫队与普通莫队不同之处就是,带修莫队可以支持修改操作,我们可以再维护一维来表示操作的时间,那么离线处理询问时,我们就需要维护 l,r,t,三根指针,同时因为是三根指针

    块的大小分成 n的2/3次方,其他地方和普通莫队维护是一样的,只是多维护了一维操作时间,可能看上去会绕一点。

    实现代码:

    #include<bits/stdc++.h>
    using namespace std;
    const int M = 1e4 + 10;
    
    struct node{
        int l,r,t,id;
        node(int l=0,int r=0,int t=0,int id=0):l(l),r(r),t(t),id(id){}
    }q[M];
    
    struct node1{
        int pos,now,old;
        node1(int pos=0,int now=0,int old=0):pos(pos),now(now),old(old){}
    }c[M];
    
    int n,m,block,l,r,num[M],a[M],now[M],flag[M*100],ans;
    //排序优先度如果l,r都在一个块中,那么优先选择t小的
    bool cmp(node a,node b){
       if(a.l/block != b.l/block){
          if(a.r/block != b.r/block){
              return a.t < b.t;
          }
          return a.r < b.r;
       }
       return a.l < b.l;
    }
    
    void add(int col,int val){
        flag[col] += val;
        if(val > 0) ans += (flag[col] == 1);
        else if(val < 0) ans -= (flag[col]==0);
    }
    
    void solve(int pos,int col){
        if(pos >= l&&pos <= r) add(col,1),add(a[pos],-1);
        a[pos] = col;
    }
    
    int main()
    {
            scanf("%d%d",&n,&m);
            block = (int)pow(n,2.0/3.0);
            for(int i = 1;i <= n;i ++){
                scanf("%d",&a[i]);
                now[i] = a[i];  //now[i] i点现在的颜色
            }
            int k = 0;
            int cnt = 0; ans = 0;
            for(int i = 0;i < m;i ++){
                char op[2];
                int x,y;
                scanf("%s%d%d",&op,&x,&y);
                if(op[0] == 'Q'){
                    //将询问的区间左右节点,在第k次修改之后,第cnt个询问等信息存到结构体q中
                    q[++cnt] = node(x,y,k,cnt);
                }
                else {
                    //将第k次修改的点的左边,要修改的颜色,这个点之前的颜色,存到结构体里
                    c[++k] = node1(x,y,now[x]);
                    now[x] = y;  //x点现在的颜色变为y
                }
            }
            sort(q+1,q+cnt+1,cmp);
            l = 1; r = 0;
            int tim = 0;
            for(int i = 1;i <= cnt;i ++){
                while(tim < q[i].t) solve(c[tim+1].pos,c[tim+1].now),tim++;
                while(tim > q[i].t) solve(c[tim].pos,c[tim].old),tim--;
                while(q[i].l < l) add(a[l-1],1),l--;
                while(q[i].l > l) add(a[l],-1),l++;
                while(q[i].r < r) add(a[r],-1),r--;
                while(q[i].r > r) add(a[r+1],1),r++;
                num[q[i].id] = ans;
            }
            for(int i = 1;i <= cnt;i ++)
                printf("%d
    ",num[i]);
        return 0;
    }

     

     

  • 相关阅读:
    win2008R2、win7不停闪屏、程序失去响应的解决办法
    “我要上春晚”刷票器
    Windows Phone 7的About模板——Your Last About Dialog
    该伙伴事务管理器已经禁止了它对远程/网络事务的支持
    安装配置apache+php+mysql小结
    [摘]CSS的优先级探讨
    利用domdrag实现flash滚动条功能
    WIN7下如何做好IE6,7的兼容性测试
    同级情况下CSS的优先级探讨
    [NHibernate] NHibernate对象关系映射工具了解
  • 原文地址:https://www.cnblogs.com/kls123/p/9426922.html
Copyright © 2011-2022 走看看