BZOJ 2120 数颜色 【带修改莫队】

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

2120: 数颜色

Time Limit: 6 Sec  Memory Limit: 259 MB
Submit: 10095  Solved: 4222
[Submit][Status][Discuss]

Description

墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问。墨墨会像你发布如下指令: 1、 Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜色的画笔。 2、 R P Col 把第P支画笔替换为颜色Col。为了满足墨墨的要求,你知道你需要干什么了吗?

Input

第1行两个整数N,M,分别代表初始画笔的数量以及墨墨会做的事情的个数。第2行N个整数,分别代表初始画笔排中第i支画笔的颜色。第3行到第2+M行,每行分别代表墨墨会做的一件事情,格式见题干部分。

Output

对于每一个Query的询问,你需要在对应的行中给出一个数字,代表第L支画笔到第R支画笔中共有几种不同颜色的画笔。

Sample Input

6 5
1 2 3 4 5 5
Q 1 4
Q 2 6
R 1 2
Q 1 4
Q 2 6

Sample Output

4
4
3
4

HINT

 

对于100%的数据,N≤10000,M≤10000,修改操作不多于1000次,所有的输入数据中出现的所有整数均大于等于1且不超过10^6。


2016.3.2新加数据两组by Nano_Ape

 

 

解题思路:

单点更新,xjb查询,莫队或者分块。

但是莫队需要离线,这里需要修改,怎么办呢?

引入第三个参数记录时间,根据时间点的不同更新答案。

 

AC code:

  1 #include <bits/stdc++.h>
  2 #define INF 0x3f3f3f3f
  3 #define LL long long
  4 using namespace std;
  5 const int MAXN = 1e4+10;
  6 const int MAXM = 1e6+10;
  7 int N, M;
  8 int h[MAXN], num[MAXN];
  9 int ans[MAXN], sum[MAXM];
 10 struct Query
 11 {
 12     int l, r, id, t;
 13 }Q[MAXN];
 14 
 15 struct Time
 16 {
 17     int ip, co, lt;
 18 }t[MAXN];
 19 int last[MAXN];
 20 
 21 bool cmp(Query a, Query b)
 22 {
 23     if(h[a.l] != h[b.l]) return h[a.l] < h[b.l];
 24     else{
 25         if(h[a.r] != h[b.r]) return h[a.r] < h[b.r];
 26         else return a.t < b.t;
 27     }
 28 }
 29 
 30 int update(int tt, int L, int R, int no)
 31 {
 32     int res = 0;
 33     int x = t[tt].ip, val = t[tt].co, lst = t[tt].lt;
 34     if(t[tt].ip >= L && t[tt].ip <= R){
 35         if(sum[num[x]] == 1) res--;
 36         sum[num[x]]--;
 37         if(no == 1){
 38             if(sum[val] == 0) res++;
 39             sum[val]++;
 40         }
 41         else if(no == -1){
 42             if(sum[lst] == 0) res++;
 43             sum[lst]++;
 44         }
 45     }
 46     if(no == 1) num[x] = val;
 47     else if(no == -1) num[x] = lst;
 48     return res;
 49 }
 50 
 51 int add(int x, int val)
 52 {
 53     int res = 0;
 54     if(val == 1 && sum[num[x]] == 0) res++;
 55     if(val == -1 && sum[num[x]] == 1) res--;
 56     sum[num[x]]+=val;
 57     return res;
 58 }
 59 
 60 int main()
 61 {
 62     scanf("%d %d", &N, &M);
 63     for(int i = 1; i <= N; i++){
 64         scanf("%d", &num[i]);
 65         last[i] = num[i];
 66     }
 67     int lim = pow(N, (double)2/3);
 68     for(int i = 1; i <= N; i++) h[i] = (i-1)/lim+1;
 69     int cnt = 0, Tcnt = 0;
 70     char com[5];
 71     for(int i = 1; i <= M; i++){
 72         scanf("%s", com);
 73         if(com[0] == 'Q'){
 74             cnt++;
 75             scanf("%d %d", &Q[cnt].l, &Q[cnt].r);
 76             Q[cnt].t = Tcnt;
 77             Q[cnt].id = cnt;
 78         }
 79         else{
 80             Tcnt++;
 81             scanf("%d %d", &t[Tcnt].ip, &t[Tcnt].co);
 82             t[Tcnt].lt = last[t[Tcnt].ip];
 83             last[t[Tcnt].ip] = t[Tcnt].co;
 84             //printf("%d %d\n", t[Tcnt].co, t[Tcnt].lt);
 85         }
 86     }
 87     sort(Q+1, Q+1+cnt, cmp);
 88 
 89     int L = 1, R = 0, T = 0, cur = 0;
 90     for(int i = 1; i <= cnt; i++){
 91         while(T < Q[i].t) cur+=update(++T, L, R, 1);
 92         while(T > Q[i].t) cur+=update(T--, L, R, -1);
 93         while(L < Q[i].l) cur+=add(L++, -1);
 94         while(L > Q[i].l) cur+=add(--L, 1);
 95         while(R < Q[i].r) cur+=add(++R, 1);
 96         while(R > Q[i].r) cur+=add(R--, -1);
 97         ans[Q[i].id] = cur;
 98     }
 99 
100     for(int i = 1; i <= cnt; i++){
101         printf("%d\n", ans[i]);
102     }
103 
104     return 0;
105 
106 }

 

posted @ 2019-02-21 13:54  莜莫  阅读(176)  评论(0编辑  收藏  举报