CF Round #466的最后一题,颇有难度,正解是带修改莫队算法。

【题意】

给定一个长度为\(n\)的数组\(a\),并且要求执行\(q\)个操作,有两种不同的操作:

①询问一个区间\([l,r]\)中集合\(\left\{c_{0},c_{1},c_{2},\cdots,c_{10^9}\right\}\)的Mex,而\(c_i\)表示数值\(i\)在\([l,r]\)中的出现次数。

②把\(a_p\)修改成\(x\)。

对每一个询问输出答案。

【题解】

典型的区间问题,不要求在线,可以考虑莫队。

有时间轴影响,故使用带修改莫队,时间复杂度应为\(O(n^{\frac{5}{3}})\)。

先对区间的移动进行分析:

使用离散化技巧,把输入数据压缩至\(n+q\)的范围内。

维护两个数组\(count1,count2\),\(count1\)记录(离散后的)每个数的出现次数,\(count2\)记录\(count1\)中的数的出现次数。

那么所求为\(count2\)中第一个为0的下标位置。

对于\(count1,count2\),我们都可以\(O(1)\)维护每个操作对数组的影响,接下来考虑如何计算答案。

\(count2\)数组的变动,让第一个为0的下标位置可能会有很大的跳跃,不好维护,那么我们注意到一个性质:

答案不会超过\(O(\sqrt{n})\),为什么呢?

假如要将\(count2_1,count2_2,\cdots,count2_k\)填满的话,至少需要\(\frac{k(k+1)}{2}\)个元素,可是数组的总长只有\(n\),所以答案必然不能太大。

那么有了这个性质,可以暴力维护答案,维护答案的总的复杂度不会超过\(O(q\sqrt{n})\)。

关于莫队,还有几个需要注意的地方:

第一个是当维护区间变化时,先考虑"伸展",再考虑"压缩",要不然会出现区间\(r<l\)的情况。

一般的莫队不会太在意这个,因为后面会再加回来,但是这题中可能会导致中间结果多减了,导致\(count2\)数组越界。

第二个是在带修改莫队时间轴移动上,千万不要颠倒了时间顺序,这其实也是常识了,不过我被这个卡了一会儿。

#include<cstdio>
#include<algorithm>
using namespace std;
#define F(i,a,b) for(int i=(a);i<=(b);++i)
#include<cmath>
int n,q,tim,cnt,sig,S;
struct Qur{int x,y,t,i;}Qs[100001];
int a[100001],b[200001],blk[100001];
inline bool cmp(Qur p1,Qur p2){return blk[p1.x]==blk[p2.x]?(blk[p1.y]==blk[p2.y]?p1.t<p2.t:blk[p1.y]<blk[p2.y]):blk[p1.x]<blk[p2.x];}
int p[100001],k[100001],k_[100001],ans[100001];
int count1[200001],count2[100001];
inline void gx1(int i){--count2[count1[i]];++count2[++count1[i]];}
inline void gx2(int i){--count2[count1[i]];++count2[--count1[i]];}
int main(){
scanf("%d%d",&n,&q); S=(int)pow(n,2.0/3.0);
F(i,1,n) scanf("%d",a+i), b[i]=a[i], blk[i]=(i-1)/S+1;
F(i,1,q){
int opt,x,y; scanf("%d%d%d",&opt,&x,&y);
if(opt==1) Qs[++cnt]=(Qur){x,y,tim,cnt};
else ++tim, b[n+tim]=y, p[tim]=x, k_[tim]=a[x], k[tim]=a[x]=y;
} F(i,1,n) a[i]=b[i];
sort(Qs+1,Qs+cnt+1,cmp); sort(b+1,b+n+tim+1); sig=unique(b+1,b+n+tim+1)-b-1;
F(i,1,n) a[i]=lower_bound(b+1,b+sig+1,a[i])-b;
F(i,1,tim) k[i]=lower_bound(b+1,b+sig+1,k[i])-b, k_[i]=lower_bound(b+1,b+sig+1,k_[i])-b;
count2[0]=sig+10;
int l=1, r=0, t=0;
F(i,1,cnt){
while(Qs[i].x<l) gx1(a[--l]);
while(Qs[i].y>r) gx1(a[++r]);
while(Qs[i].x>l) gx2(a[l++]);
while(Qs[i].y<r) gx2(a[r--]);
while(Qs[i].t>t) ++t, (Qs[i].x<=p[t]&&p[t]<=Qs[i].y)?gx1(k[t]),gx2(k_[t]):void(0), a[p[t]]=k[t];
while(Qs[i].t<t) (Qs[i].x<=p[t]&&p[t]<=Qs[i].y)?gx1(k_[t]),gx2(k[t]):void(0), a[p[t]]=k_[t], --t;
for(ans[Qs[i].i]=1;count2[ans[Qs[i].i]];++ans[Qs[i].i]);
}
F(i,1,cnt) printf("%d\n",ans[i]);
return 0;
}

【codeforces】940F题解的更多相关文章

  1. codeforces#536题解

    CodeForces#536 A. Lunar New Year and Cross Counting Description: Lunar New Year is approaching, and ...

  2. Machine Learning CodeForces - 940F(带修改的莫队)

    题解原文地址:https://www.cnblogs.com/lujiaju6555/p/8468709.html 给数组a,有两种操作,1 l r查询[l,r]中每个数出现次数的mex,注意是出现次 ...

  3. codeforces 1093 题解

    12.18 update:补充了 $ F $ 题的题解 A 题: 题目保证一定有解,就可以考虑用 $ 2 $ 和 $ 3 $ 来凑出这个数 $ n $ 如果 $ n $ 是偶数,我们用 $ n / 2 ...

  4. Codeforces 940F Machine Learning (带修改莫队)

    题目链接  Codeforces Round #466 (Div. 2) Problem F 题意  给定一列数和若干个询问,每一次询问要求集合$\left\{c_{0}, c_{1}, c_{2}, ...

  5. codeforces 940F 带修改的莫队

    F. Machine Learning time limit per test 4 seconds memory limit per test 512 megabytes input standard ...

  6. Codeforces Numbers 题解

    这题只需要会10转P进制就行了. PS:答案需要约分,可以直接用c++自带函数__gcd(x,y). 洛谷网址 Codeforces网址 Code(C++): #include<bits/std ...

  7. Codeforces 691E题解 DP+矩阵快速幂

    题面 传送门:http://codeforces.com/problemset/problem/691/E E. Xor-sequences time limit per test3 seconds ...

  8. Codeforces 833B 题解(DP+线段树)

    题面 传送门:http://codeforces.com/problemset/problem/833/B B. The Bakery time limit per test2.5 seconds m ...

  9. Codeforces 840C 题解(DP+组合数学)

    题面 传送门:http://codeforces.com/problemset/problem/840/C C. On the Bench time limit per test2 seconds m ...

随机推荐

  1. zabbix 自定义监控nginx

    zabbix自定义nginx监控项 查看nginx编译安装是否加上该选项,如果没有请重新编译安装 配置nginx.conf vim /usr/local/cpgroup/nginx/conf/vhos ...

  2. 【BZOJ1922】大陆争霸(最短路)

    [BZOJ1922]大陆争霸(最短路) 题面 BZOJ 洛谷 题解 最短路变形题. 定义\(dis\)表示最短路,\(d\)表示最早可以进入当前点的时间.显然\(d=max(max(dis_v,d_v ...

  3. python之插入排序

    插入排序的基本操作就是将一个数据插入到已经排好序的有序数据中,从而得到一个新的.个数加一的有序数据,算法适用于少量数据的排序,时间复杂度为O(n^2).是稳定的排序方法.插入算法把要排序的数组分成两部 ...

  4. 【IOI 2018】Highway 高速公路收费

    这是一道极好的图论题,虽然我一开始只会做$18$分,后来会做$51$分,看着题解想了好久才会做(吐槽官方题解:永远只有一句话),但这的确是一道好题,值得思考,也能启发思维. 如果要讲这道题,还是要从部 ...

  5. 开源nginx_lua_waf部署安装

      0x01 前言 ngx_lua_waf实现 WAF一句话描述,就是解析HTTP请求(协议解析模块),规则检测(规则模块),做不同的防御动作(动作模块),并将防御过程(日志模块)记录下来.所以本文中 ...

  6. 单点登录(十七)----cas4.2.x登录mongodb验证方式成功后返回更多信息更多属性到客户端

    我们在之前已经完成了cas4.2.x登录使用mongodb验证方式登录成功了.也解决了登录名中使用中文乱码的问题. 单点登录(十三)-----实战-----cas4.2.X登录启用mongodb验证方 ...

  7. Android Launcher分析和修改

    Android Launcher分析和修改 http://www.cnblogs.com/mythou/category/499819.html Android Launcher分析和修改1——Lau ...

  8. C++析构函数的自动调用(用于父类指针指向子类对象,内存泄漏问题)

    class A {public:A() { printf("A \n"); }~A() { printf(" ~A \n"); } // 这里不管写不写virt ...

  9. beego 定义一个存储变量的容器

    golang 这种语言相对于 php 有个好处是,不用每次请求都重复一些不必要的初始化操作,golang 进程开启之后,即使请求结束,相关的资源也会驻留在内存中. 所以我们可以把一些不需要重复初始化的 ...

  10. ACF/PACF,残差白噪声的检验问题

    关于自相关.偏自相关: 一.自协方差和自相关系数       p阶自回归AR(p)       自协方差 r(t,s)=E[X(t)-EX(t)][X(s)-EX(s)]       自相关系数ACF ...