BZOJ2120 数颜色 —— 待修改莫队

题目链接:https://vjudge.net/problem/HYSBZ-2120

 

2120: 数颜色

Time Limit: 6 Sec  Memory Limit: 259 MB
Submit: 6898  Solved: 2781
[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

 

 

题意:

查询区间颜色种数,且带修改。

 

 

代码如下:

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 #include <vector>
  6 #include <cmath>
  7 #include <queue>
  8 #include <stack>
  9 #include <map>
 10 #include <string>
 11 #include <set>
 12 using namespace std;
 13 typedef long long LL;
 14 const int INF = 2e9;
 15 const LL LNF = 9e18;
 16 const int MOD = 1e9+7;
 17 const int MAXN = 1e6+10;
 18 
 19 int val[MAXN], tmp[MAXN];
 20 int block, sum[MAXN], Ans[MAXN];
 21 int num1, num2;
 22 
 23 struct Node
 24 {
 25     //index记录查询的编号, t记录查询时执行了多少步修改
 26     int l, r, index, t;
 27     bool operator<(const Node&x) const{
 28         if(l/block!=x.l/block) return l/block<x.l/block;
 29         else if(r!=x.r) return r<x.r;
 30         else return  t<x.t;
 31     }
 32 }q[MAXN];
 33 
 34 struct
 35 {
 36     //preCol记录修改前pos位的颜色, nowCol记录修改后pos位的颜色
 37     int pos, nowCol, preCol;
 38 }op[MAXN];
 39 
 40 int L, R, T, ans;
 41 void modifyTime(int pos, int col)
 42 {
 43     if(L<=pos && pos<=R)
 44     {
 45         sum[val[pos]]--;
 46         if(sum[val[pos]]==0) ans--;
 47         val[pos] = col;
 48         sum[val[pos]]++;
 49         if(sum[val[pos]]==1) ans++;
 50     }
 51     else val[pos] = col;
 52 }
 53 
 54 void add(int pos)
 55 {
 56     sum[val[pos]]++;
 57     if(sum[val[pos]]==1) ans++;
 58 }
 59 
 60 void del(int pos)
 61 {
 62     sum[val[pos]]--;
 63     if(sum[val[pos]]==0) ans--;
 64 }
 65 
 66 void work()
 67 {
 68     L = 1, R = 0, T = 0, ans = 0;
 69     memset(sum, 0, sizeof(sum));
 70     for(int i = 1; i<=num1; i++)
 71     {
 72         while(T<q[i].t) T++, modifyTime(op[T].pos, op[T].nowCol);
 73         while(T>q[i].t) modifyTime(op[T].pos, op[T].preCol), T--;
 74         while(L<q[i].l) del(L), L++;
 75         while(L>q[i].l) L--, add(L);
 76         while(R<q[i].r) R++, add(R);
 77         while(R>q[i].r) del(R), R--;
 78         Ans[q[i].index] = ans;
 79     }
 80 }
 81 
 82 int main()
 83 {
 84     int n, m;
 85     while(scanf("%d%d", &n,&m)!=EOF)
 86     {
 87         block = sqrt(n);
 88         for(int i = 1; i<=n; i++)
 89         {
 90             scanf("%d", &val[i]);
 91             tmp[i] = val[i];
 92         }
 93 
 94         num1 = num2 = 0;
 95         for(int i = 1; i<=m; i++)
 96         {
 97             char s[2]; int x, y;
 98             scanf("%s%d%d", s, &x, &y);
 99             if(s[0]=='Q')
100             {
101                 q[++num1].index = num1;
102                 q[num1].t = num2;
103                 q[num1].l = x;
104                 q[num1].r = y;
105             }
106             else    //tmp用于记录动态修改时每个位置上的颜色
107             {
108                 op[++num2].pos = x;
109                 op[num2].nowCol = y;
110                 op[num2].preCol = tmp[x];
111                 tmp[x] = y;
112             }
113         }
114 
115         sort(q+1, q+1+num1);
116         work();
117         for(int i = 1; i<=num1; i++)
118             printf("%d\n", Ans[i]);
119     }
120 }
View Code

 

直接暴力也行:

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 #include <vector>
  6 #include <cmath>
  7 #include <queue>
  8 #include <stack>
  9 #include <map>
 10 #include <string>
 11 #include <set>
 12 using namespace std;
 13 typedef long long LL;
 14 const int INF = 2e9;
 15 const LL LNF = 9e18;
 16 const int MOD = 1e9+7;
 17 const int MAXN = 1e6+10;
 18 
 19 int val[MAXN], tmp[MAXN];
 20 int block, sum[MAXN], Ans[MAXN];
 21 int num1, num2;
 22 
 23 struct Node
 24 {
 25     //index记录查询的编号, t记录查询时执行了多少步修改
 26     int l, r, index, t;
 27 }q[MAXN];
 28 
 29 struct
 30 {
 31     //preCol记录修改前pos位的颜色, nowCol记录修改后pos位的颜色
 32     int pos, nowCol, preCol;
 33 }op[MAXN];
 34 
 35 int L, R, T, ans;
 36 void modifyTime(int pos, int col)
 37 {
 38     if(L<=pos && pos<=R)
 39     {
 40         sum[val[pos]]--;
 41         if(sum[val[pos]]==0) ans--;
 42         val[pos] = col;
 43         sum[val[pos]]++;
 44         if(sum[val[pos]]==1) ans++;
 45     }
 46     else val[pos] = col;
 47 }
 48 
 49 void add(int pos)
 50 {
 51     sum[val[pos]]++;
 52     if(sum[val[pos]]==1) ans++;
 53 }
 54 
 55 void del(int pos)
 56 {
 57     sum[val[pos]]--;
 58     if(sum[val[pos]]==0) ans--;
 59 }
 60 
 61 void work()
 62 {
 63     L = 1, R = 0, T = 0, ans = 0;
 64     memset(sum, 0, sizeof(sum));
 65     for(int i = 1; i<=num1; i++)
 66     {
 67         while(T<q[i].t) T++, modifyTime(op[T].pos, op[T].nowCol);
 68         while(T>q[i].t) modifyTime(op[T].pos, op[T].preCol), T--;
 69         while(L<q[i].l) del(L), L++;
 70         while(L>q[i].l) L--, add(L);
 71         while(R<q[i].r) R++, add(R);
 72         while(R>q[i].r) del(R), R--;
 73         Ans[q[i].index] = ans;
 74     }
 75 }
 76 
 77 int main()
 78 {
 79     int n, m;
 80     while(scanf("%d%d", &n,&m)!=EOF)
 81     {
 82         for(int i = 1; i<=n; i++)
 83         {
 84             scanf("%d", &val[i]);
 85             tmp[i] = val[i];
 86         }
 87 
 88         num1 = num2 = 0;
 89         for(int i = 1; i<=m; i++)
 90         {
 91             char s[2]; int x, y;
 92             scanf("%s%d%d", s, &x, &y);
 93             if(s[0]=='Q')
 94             {
 95                 q[++num1].index = num1;
 96                 q[num1].t = num2;
 97                 q[num1].l = x;
 98                 q[num1].r = y;
 99             }
100             else    //tmp用于记录动态修改时每个位置上的颜色
101             {
102                 op[++num2].pos = x;
103                 op[num2].nowCol = y;
104                 op[num2].preCol = tmp[x];
105                 tmp[x] = y;
106             }
107         }
108 
109         work();
110         for(int i = 1; i<=num1; i++)
111             printf("%d\n", Ans[i]);
112     }
113 }
View Code

 

posted on 2018-01-20 17:46  h_z_cong  阅读(239)  评论(0编辑  收藏  举报

导航