• 带修改的莫队


    彩色盒子

    sol:彩色盒子可以用分块来做(有题解),也可以用莫队来做,带修改操作。
    如颜色:1 3 2 5 7 8 2 4 6
    Q:[1,9]  //询问区间1~9的颜色数
    M:3 4   //将第三个位置的颜色改为颜色4
    M:1 5
    Q:[1,3]
    若用莫队来做,按查询排序,依次得到区间[1,3],[1,9]。
    但,在做查询[1,3]时,查询操作的前面有两个修改操作。
    怎么解决:定义一个时间now,相当于给每一个操作依次打上一个时间戳,now初值为0,如上面四个操作,now值依次为1,2,3,4.
    现在我们做查询[1,3],now=4,那我们就要看在这个询问前是否有修改操作,本样例有两次修改,修改后,再做莫队。
    接下来我们做查询[1,9],now=1,我们查询这个区间时本没有两次修改操作,所以又把前面做的两次修改操作撤销。
    这样就顺利得到我们想要的结果。

    代码如下:

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <algorithm>
      4 using namespace std;
      5 typedef long long ll;
      6 #define space putchar(' ')
      7 #define enter putchar('
    ')
      8 template <class T>
      9 void read(T &x){
     10     char c;
     11     bool op = 0;
     12     while(c = getchar(), c < '0' || c > '9')
     13         if(c == '-') op = 1;
     14     x = c - '0';
     15     while(c = getchar(), c >= '0' && c <= '9')
     16         x = x * 10 + c - '0';
     17     if(op) x = -x;
     18 }
     19 template <class T>
     20 void write(T x){
     21     if(x < 0) x = -x, putchar('-');
     22     if(x >= 10) write(x / 10);
     23     putchar('0' + x % 10);
     24 }
     25 const int N = 10005, M = 1000005, B = 464;
     26 int n, m, pl = 1, pr = 0, cur, res, ans[N], a[N], cnt[M];
     27 int idxC, idxQ, tim[N], pos[N], val[N], pre[N];
     28 #define bel(x) (((x) - 1) / B + 1)
     29 struct query
     30 {
     31     int id, tim, l, r;
     32     bool operator < (const query &b) const
     33     {
     34         if(bel(l) != bel(b.l)) return l < b.l;
     35         if(bel(r) != bel(b.r)) return r < b.r;
     36         return id < b.id;
     37     }
     38 } q[N];
     39 void change_add(int cur)
     40 {
     41     if(pos[cur] >= pl && pos[cur] <= pr) //如果这个修改操作发生在我们当前询问的区间中 
     42     {
     43         cnt[a[pos[cur]]]--; //则从前这个点的color的出现次数-1 
     44         if(!cnt[a[pos[cur]]]) //如果减少后变成了0,则出现的总color数-1 
     45            res--;
     46     }
     47     pre[cur] = a[pos[cur]];//记下从前的color,方便今后如果后面再加回来时进行操作 
     48     a[pos[cur]] = val[cur]; //换上新的color
     49     if(pos[cur] >= pl && pos[cur] <= pr) //同上 
     50     {
     51         if(!cnt[a[pos[cur]]]) //如果新color出现的次数从0变成1,则总color+1 
     52             res++;
     53         cnt[a[pos[cur]]]++;
     54     }
     55 }
     56 void change_del(int cur)
     57 {
     58     if(pos[cur] >= pl && pos[cur] <= pr)  
     59     {
     60         cnt[a[pos[cur]]]--;
     61         if(!cnt[a[pos[cur]]]) res--;
     62     }
     63     a[pos[cur]] = pre[cur];
     64     if(pos[cur] >= pl && pos[cur] <= pr)
     65     {
     66         if(!cnt[a[pos[cur]]]) res++;
     67         cnt[a[pos[cur]]]++;
     68     }
     69 }
     70 void change(int now)
     71 {
     72     while(cur < idxC && tim[cur + 1] <= now)//找now之前未作的修改
     73     //cur代表目前的修改操作进行到哪一个了
    74 //cur+1到当前询问时间点now之间还有些修改操作还没有做,加进来  75 change_add(++cur); 76 while(cur && tim[cur] > now) 77 //也有可能是多做了修改操作,于是删除这些修改操作 78 change_del(cur--); 79 } 80 void add(int p) 81 { 82 if(!cnt[a[p]]) 83 res++; 84 cnt[a[p]]++; 85 } 86 void del(int p) 87 { 88 cnt[a[p]]--; 89 if(!cnt[a[p]]) 90 res--; 91 } 92 bool isQ() 93 { 94 char op[2]; 95 scanf("%s", op); 96 return op[0] == 'Q'; 97 } 98 int main() 99 { 100 read(n), read(m); 101 for(int i = 1; i <= n; i++) 102 read(a[i]); 103 for(int i = 1; i <= m; i++) 104 { 105 if(isQ()) //查询操作 106 { 107 idxQ++; 108 q[idxQ].id = idxQ; //表示其为第多少个查询操作 109 q[idxQ].tim = i; //这个查询操作发生的时间 110 read(q[idxQ].l); 111 read(q[idxQ].r); 112 } 113 else //修改操作 114 { 115 tim[++idxC] = i; //第idxc个修改操作发生的时间 116 read(pos[idxC]); //修改的位置 117 read(val[idxC]); //修改后的color 118 } 119 } 120 sort(q + 1, q + idxQ + 1); 121 for(int i = 1; i <= idxQ; i++) 122 { 123 change(q[i].tim); 124 //以当前这个查询为基准,是否有修改操作没有做,或者多做了 125 while(pl > q[i].l) add(--pl); 126 while(pr < q[i].r) add(++pr); 127 while(pl < q[i].l) del(pl++); 128 while(pr > q[i].r) del(pr--); 129 ans[q[i].id] = res; 130 } 131 for(int i = 1; i <= idxQ; i++) 132 write(ans[i]), enter; 133 return 0; 134 }
  • 相关阅读:
    iframe+json
    qw
    MySql数据类型和Java数据类型对应一览
    MyEclipse生成get/set注释
    Redis集群_主从配置
    MyBatis输出sql需要log4j.properties配置
    默认没有创建两次定时实例的
    spring+freemarker+redis
    jquery easyui 扩展验证
    vs2010 安装 Ajax Control Toolkit
  • 原文地址:https://www.cnblogs.com/cutepota/p/12887756.html
Copyright © 2020-2023  润新知