bzoj 2453 : 维护队列 带修莫队

2453: 维护队列

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 952  Solved: 432
[Submit][Status][Discuss]

Description

你小时候玩过弹珠吗?

小朋友A有一些弹珠,A喜欢把它们排成队列,从左到右编号为1到N。为了整个队列鲜艳美观,小朋友想知道某一段连续弹珠中,不同颜色的弹珠有多少。当然,A有时候会依据个人喜好,替换队列中某个弹珠的颜色。但是A还没有学过编程,且觉得头脑风暴太浪费脑力了,所以向你来寻求帮助。

Input

输入文件第一行包含两个整数N和M。

第二行N个整数,表示初始队列中弹珠的颜色。

接下来M行,每行的形式为“Q L R”或“R x c”,“Q L R”表示A想知道从队列第L个弹珠到第R个弹珠中,一共有多少不同颜色的弹珠,“R x c”表示A把x位置上的弹珠换成了c颜色。

Output

对于每个Q操作,输出一行表示询问结果。

Sample Input

2 3
1 2
Q 1 2
R 1 2
Q 1 2

Sample Output

2
1

HINT

对于100%的数据,有1 ≤ N ≤ 10000, 1 ≤ M ≤ 10000,小朋友A不会修改超过1000次,所有颜色均用1到10^6的整数表示。

Source

2011福建集训

  把询问和修改分开排序,修改按时间排,询问以左端点所在块为第一关键字,右端点所在块为第二关键字,时间为第三关键字排序。

  维护左右时间三个指针,不断修改还原。

  块大小为$n^{\frac{2}{3}}$。

  左指针每个询问走$n^{\frac{2}{3}}$。

  右指针同理,不过要多上每次总从左走到右的复杂度,总共$n\times n^{\frac{2}{3}}+n\times n^{\frac{1}{3}}$。

  时间指针每次左右端点所在块变化重新开始走,一共$n^{\frac{2}{3}}$个不同的左右块匹配数,复杂度$n\times n^{\frac{2}{3}}$.

  好像块开100比较快。

  

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #define d 100
  6 #define N 10005
  7 using namespace std;
  8 int n,m;
  9 int c[N];
 10 struct node
 11 {
 12     int l,r,t,pr;
 13     node(){l=r=t=0;}
 14 }q[N],g[N];
 15 int cnt1,cnt2;
 16 bool cmp1(const node &aa,const node &bb)
 17 {
 18     return aa.t<bb.t;
 19 }
 20 int be1[N],be2[N];
 21 bool cmp2(const node &aa,const node &bb)
 22 {
 23     if(be1[aa.l]==be1[bb.l])
 24     {
 25         if(be2[aa.r]==be2[bb.r])return aa.t<bb.t;
 26         return aa.r<bb.r;
 27     }
 28     return aa.l<bb.l;
 29 }
 30 int ans[N];
 31 int now[N*100],cnt;
 32 void solve()
 33 {
 34     int p1,p2,p;
 35     memset(now,0,sizeof(now));
 36     now[c[1]]=1;cnt=1;g[cnt1+1].t=10005;
 37     p=p1=1;
 38     p2=0;
 39     for(int i=1;i<=cnt2;i++)
 40     {
 41         while(g[p2+1].t<q[i].t)
 42         {
 43             p2++;
 44             int tmp=c[g[p2].l];
 45             g[p2].pr=tmp;
 46             c[g[p2].l]=g[p2].r;
 47             if(g[p2].l<=p&&g[p2].l>=p1)
 48             {
 49                 now[tmp]--;
 50                 if(!now[tmp])cnt--;
 51                 now[g[p2].r]++;
 52                 if(now[g[p2].r]==1)cnt++;
 53             }
 54         }
 55         while(g[p2].t>q[i].t)
 56         {
 57
 58             c[g[p2].l]=g[p2].pr;
 59             if(g[p2].l<=p&&g[p2].l>=p1)
 60             {
 61                 now[g[p2].r]--;
 62                 if(!now[g[p2].r])cnt--;
 63                 now[g[p2].pr]++;
 64                 if(now[g[p2].pr]==1)cnt++;
 65             }
 66             p2--;
 67         }
 68         while(p<q[i].r)
 69         {
 70             p++;now[c[p]]++;
 71             if(now[c[p]]==1)cnt++;
 72         }
 73         while(p>q[i].r)
 74         {
 75             now[c[p]]--;if(!now[c[p]])cnt--;
 76             p--;
 77         }
 78         while(p1<q[i].l)
 79         {
 80             now[c[p1]]--;if(!now[c[p1]])cnt--;
 81             p1++;
 82         }
 83         while(p1>q[i].l)
 84         {
 85             p1--;now[c[p1]]++;
 86             if(now[c[p1]]==1)cnt++;
 87         }
 88         ans[q[i].t]=cnt;
 89     }
 90 }
 91 int main()
 92 {
 93     scanf("%d%d",&n,&m);
 94     for(int i=1;i<=n;i++)scanf("%d",&c[i]);
 95     for(int i=1;i<=n;i++)
 96     {
 97         be1[i]=be2[i]=(i-1)/d+1;
 98     }
 99     memset(ans,-1,sizeof(ans));
100     char s[2];
101     for(int i=1;i<=m;i++)
102     {
103         scanf("%s",s);
104         if(s[0]==‘R‘)
105         {
106             cnt1++;
107             scanf("%d%d",&g[cnt1].l,&g[cnt1].r);
108             g[cnt1].t=i;
109         }
110         else
111         {
112             cnt2++;
113             scanf("%d%d",&q[cnt2].l,&q[cnt2].r);
114             q[cnt2].t=i;
115         }
116     }
117     sort(q+1,q+cnt2+1,cmp2);
118     sort(g+1,g+cnt1+1,cmp1);
119     solve();
120     for(int i=1;i<=m;i++)
121     {
122         if(ans[i]!=-1)printf("%d\n",ans[i]);
123     }
124     return 0;
125 }
时间: 2024-10-12 00:41:00

bzoj 2453 : 维护队列 带修莫队的相关文章

bzoj 2453: 维护队列

2453: 维护队列 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1079  Solved: 503[Submit][Status][Discuss] Description 你小时候玩过弹珠吗? 小朋友A有一些弹珠,A喜欢把它们排成队列,从左到右编号为1到N.为了整个队列鲜艳美观,小朋友想知道某一段连续弹珠中,不同颜色的弹珠有多少.当然,A有时候会依据个人喜好,替换队列中某个弹珠的颜色.但是A还没有学过编程,且觉得头脑风暴太浪费脑力了,所以向

【BZOJ-3052】糖果公园 树上带修莫队算法

3052: [wc2013]糖果公园 Time Limit: 200 Sec  Memory Limit: 512 MBSubmit: 883  Solved: 419[Submit][Status][Discuss] Description Input Output Sample Input Sample Output 84 131 27 84 HINT Source Solution 树上带修莫队 本质还是树上莫队,详情可以转 BZOJ-3757苹果树 但是这里需要修改,就需要一些特殊的地方

bzoj4129 Haruna’s Breakfast 树上带修莫队+分块

题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4129 题解 考虑没有修改的序列上的版本应该怎么做: 弱化的题目应该是这样的: 给定一个序列,每次询问区间 \([l, r]\) 中元素的最小没有出现的自然数. 这个弱化的版本可以用离线+线段树二分水掉.但是这个做法显然不太好搬到树上做. 上面的弱化版还有一个莫队做法:可以用莫队维护出来每一个区间的每一个数的出现为次数.把出现过的数通过分块表示出来,于是查询的时候枚举每一个块,寻找第一个不满的

【带修莫队】【权值分块】bzoj3196 Tyvj 1730 二逼平衡树

这题用了三种算法写: 分块+二分:O(n*sqrt(n*log(n)) 函数式权值分块:O(n*sqrt(n)) 带修莫队+权值分块:O(n5/3) 结果……复杂度越高的实际上跑得越快……最后这个竟然进第一页了…… #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; int f,C; inline void R(int &

2120: 数颜色(带修莫队)

题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=2120 2120: 数颜色 Time Limit: 6 Sec  Memory Limit: 259 MBSubmit: 10514  Solved: 4398[Submit][Status][Discuss] Description 墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问.墨墨会像你发布如下指令: 1. Q L R代表询问你从第L支画笔到第R

CF940F Machine Learning(带修莫队)

首先显然应该把数组离散化,然后发现是个带修莫队裸题,但是求mex比较讨厌,怎么办?其实可以这样求:记录每个数出现的次数,以及出现次数的出现次数.至于求mex,直接暴力扫最小的出现次数的出现次数为0的正整数,就一句话,这样看似会超时,实际上是O(√n)的复杂度.为什么?假设存在出现1,2,...,x的出现次数,则Σi(1<=i<=x)<=n,即x*(x+1)<=2*n,所以x至多是√n级别.很多人再把出现次数分块,根本没必要.然后考虑把数组分块的块大小,每次移动左指针,为O(n*块大

莫队 + 带修莫队

莫队其实就是一个带优化的暴力,通过将区间询问按一定规则进行排序,从而优化过程,求出答案. 举一例子:(例子不具备权威性,只是让读者了解莫队是干啥的) /* 输入四个区间 1 4 初始条件,L= R = 0, 将R遍历到4 需要走4步 L走一步,共5次 4 8 继承上一次 L 和 R 的值,L从1到4 需要3次,R从4到8,需4次, 总计8次 2 9 同理继承, L回退2次, R前进一次 总计3次 1 2 同理,L回退1次,R回退7次 总计8次 如果直接暴力,计算机将要计算 5+8+3+8=24次

数颜色(带修莫队模板)

数颜色(luogu) Description 题目描述 墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问.墨墨会向你发布如下指令: 1. Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜色的画笔. 2. R P Col 把第P支画笔替换为颜色Col. 为了满足墨墨的要求,你知道你需要干什么了吗? 输入格式 第1行两个整数N,M,分别代表初始画笔的数量以及墨墨会做的事情的个数. 第2行N个整数,分别代表初始画笔排中第i支画笔的颜色. 第3行到第2+M行

BZOJ.2453.维护队列([模板]带修改莫队)

题目链接 带修改莫队: 普通莫队的扩展,依旧从[l,r,t]怎么转移到[l+1,r,t],[l,r+1,t],[l,r,t+1]去考虑 对于当前所在的区间维护一个vis[l~r]=1,在修改值时根据是否在当前区间内修改即可. 块大小取\(O(n^{\frac{2}{3}})\),排序依次按左端点所在块.右端点所在块.修改次数(时间) 复杂度为\(O(n^{\frac{5}{3}})\) (证明在这) #include <cmath> #include <cstdio> #inclu