码迷,mamicode.com
首页 > 编程语言 > 详细

莫队算法(可修改)

时间:2019-09-20 20:49:18      阅读:73      评论:0      收藏:0      [点我收藏+]

标签:col   莫队   问题   pre   题目   pac   --   描述   online   

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

2120: 数颜色

时间限制: 6 Sec  内存限制: 259 MB
提交: 11694  解决: 4853
[提交][][]

题目描述

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

输入

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

输出

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

莫队可以修改?那不是爆炸了吗。这类爆炸的问题被称为带修莫队(可持久化莫队)。

按照美妙类比思想,可以引入一个“修改时间”,表示当前询问是发生在前Time个修改操作后的。也就是说,在进行莫队算法时,看看当前的询问和时间指针是否相符,然后进行时光倒流或者时光推移操作来保证答案正确性。

Sort的构造:仅靠原来的sort关键字会使得枚举每个询问都可能因为时间指针移动的缘故要移动n次,总共就n^2次,那还不如写暴力。为了防止这样的事情发生,再加入第三关键字Tim:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=10000+10;
 4 struct Query{
 5     int l,r,Tim,ID;
 6 }q[maxn];
 7 struct Change{
 8     int pos,New,Old;
 9 }c[maxn];
10 int s[maxn],Be[maxn];
11 int now[maxn],ans[maxn];
12 int color[maxn*100];
13 int Ans,l=1,r;
14 bool cmp(Query a,Query b)
15 {
16     return Be[a.l]==Be[b.l]?(Be[a.r]==Be[b.r]?a.Tim<b.Tim:a.r<b.r):a.l<b.l;
17 }
18 void revise(int x,int d)
19 {
20     color[x]+=d;
21     if(d>0) Ans+=color[x]==1;
22     if(d<0) Ans-=color[x]==0;
23 }
24 void going(int x,int d)
25 {
26     if(l<=x&&x<=r) 
27         revise(d,1),revise(s[x],-1);
28     s[x]=d;
29 }
30 int main()
31 {
32     int n,m; 
33     scanf("%d%d",&n,&m);
34     int unit=pow(n,2.0/3); 
35     for(int i=1;i<=n;i++){
36         scanf("%d",&s[i]);
37         now[i]=s[i];
38         Be[i]=i/unit+1; //分块
39     }
40     int Time=0,t=0;
41     while(m--){
42         char sign; int x,y;
43         scanf(" %c %d%d",&sign,&x,&y);
44         if(sign==Q) q[++t]=(Query){x,y,Time,t};
45         else c[++Time]=(Change){x,y,now[x]},now[x]=y;
46     }
47     sort(q+1,q+t+1,cmp);
48     int T=0;
49     for(int i=1;i<=t;i++){
50         while(T<q[i].Tim) going(c[T+1].pos,c[T+1].New),T++;
51         while(T>q[i].Tim) going(c[T].pos,c[T].Old),T--;
52         while(l<q[i].l) revise(s[l],-1),l++;
53         while(l>q[i].l) revise(s[l-1],1),l--;
54         while(r<q[i].r) revise(s[r+1],1),r++;
55         while(r>q[i].r) revise(s[r],-1),r--;
56         ans[q[i].ID]=Ans;
57     }
58     for(int i=1;i<=t;i++) 
59         printf("%d\n",ans[i]);
60     return 0;
61 }

 

 

莫队算法(可修改)

标签:col   莫队   问题   pre   题目   pac   --   描述   online   

原文地址:https://www.cnblogs.com/pangbi/p/11559732.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!