当前位置:网站首页>莫队学习总结(二)
莫队学习总结(二)
2022-07-26 09:29:00 【逃夭丶】
本文参考自:https://www.cnblogs.com/ouuan/p/MoDuiTutorial.html
带修莫队
普通莫队只能解决没有修改的问题,那么带修改的问题怎么解决?带修莫队就是一种支持单点修改的莫队算法。
算法简介
还是对询问进行排序,每次询问除了左端点和右端点还要记录这个询问是在第几次修改之后(时间),以左端点所在块为第一关键字,以右端点所在块为第二关键字,以时间为第三关键字进行排序。
暴力查询时,如果当前修改时间比询问时间的修改数少那就没修改的进行修改,反之回退。
需要注意的是,修改部分分为两部分:
- 若修改的位置在当前区间内,需要更新答案(del原来的颜色,add修改后的颜色)
- 无论修改的位置是否在当前区间内,都要进行修改(以供add和del函数在以后更新答案)
分块大小的选择以及复杂度
视作n==m的话,取 B = n 2 3 n^\frac{2}{3} n32 时,复杂度 O(nlogn + n 2 3 n^\frac{2}{3} n32)。
例题1:P1903 [国家集训队]数颜色 / 维护队列
O 2 O_2 O2才过的,它卡一点常数。
#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cctype>
#include<vector>
#include<stack>
#include<queue>
#include<ctime>
#include<utility>
#include<map>
#define ll long long
#define ld long double
#define ull unsigned long long
using namespace std;
const int INF = 100000;
const double eps = 1e-6;
const int maxn = 2000000;
int n,m,nm;
int col[maxn],cnt[maxn],sum;
int ans[maxn];
struct Change{
int p,col;
}c[maxn];
struct Query{
int l,r,t;
int id;
bool operator < (Query& b){
if(l/nm==b.l/nm){
if(r/nm==b.r/nm) return t < b.t;
return r < b.r;
}
return l < b.l;
}
}q[maxn];
void add(int x)
{
if(cnt[x]==0) sum++;
cnt[x]++;
}
void del(int x)
{
cnt[x]--;
if(cnt[x]==0) sum--;
}
void changx(int x,int ti)
{
if(c[ti].p>=q[x].l&&c[ti].p<=q[x].r){
del(col[c[ti].p]);
add(c[ti].col);
}
swap(col[c[ti].p],c[ti].col);
}
int main(void)
{
char cmd[4];
scanf("%d%d",&n,&m);
nm = pow(n,0.66666);
for(int i=1;i<=n;i++){
scanf("%d",&col[i]);
}
int cntq,cntc,x,y;
cntq = cntc = 0;
for(int i=1;i<=m;i++){
scanf("%s",cmd);
if(cmd[0]=='Q'){
cntq++;
scanf("%d%d",&x,&y);
q[cntq].id = cntq;
q[cntq].l = x;q[cntq].r = y;
q[cntq].t = cntc;
}
else{
cntc++;
scanf("%d%d",&x,&y);
c[cntc].p = x;c[cntc].col = y;
}
}
sort(q+1,q+cntq+1);
int l = 2,r = 1,now = 0;
for(int i=1;i<=cntq;i++){
while(l>q[i].l)
add(col[--l]);
while(r<q[i].r)
add(col[++r]);
while(l<q[i].l)
del(col[l++]);
while(r>q[i].r)
del(col[r--]);
while(now<q[i].t)
changx(i,++now);
while(now>q[i].t)
changx(i,now--);
ans[q[i].id] = sum;
}
for(int i=1;i<=cntq;i++){
printf("%d\n",ans[i]);
}
return 0;
}
例题2:CF940F Machine Learning
题意翻译
给你一个数组 { a i } \{a_i\} { ai}支持两种操作:
1、查询区间[l,r]中每个数字出现次数的mex。
2、单点修改某一个位置的值。
mex指的是一些数字中最小的未出现的自然数。值得注意的是,区间[l,r]总有数字是没有出现过的,所以答案不可能为0.
n , Q ≤ 1 0 5 n,Q\le10^5 n,Q≤105
注意一点,就是离散化原序列里的数字和修改的数字
sort(pcol,pcol+tot);
tot = unique(pcol,pcol+tot)-pcol;
for(int i=1;i<=n;i++){
col[i] = lower_bound(pcol,pcol+tot,col[i]) - pcol;
}
for(int i=1;i<=cntc;i++){
c[i].col = lower_bound(pcol,pcol+tot,c[i].col) - pcol;
}
#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cctype>
#include<vector>
#include<stack>
#include<queue>
#include<ctime>
#include<utility>
#include<map>
#define ll long long
#define ld long double
#define ull unsigned long long
using namespace std;
const int INF = 100000;
const double eps = 1e-6;
const int maxn = 2000000;
int n,m,nm;
int pcol[maxn],tot;
int col[maxn],cnt[maxn];
int ans[maxn],pcnt[maxn];
int cntq,cntc,x,y;
int l = 1,r = 0,now = 0;
struct Change{
int p,col;
}c[maxn];
struct Query{
int l,r,t;
int id;
bool operator < (Query& b){
if(l/nm==b.l/nm){
if(r/nm==b.r/nm) return t < b.t;
return r < b.r;
}
return l < b.l;
}
}q[maxn];
inline void add(int x)
{
pcnt[cnt[x]]--;
cnt[x]++;
pcnt[cnt[x]]++;
}
inline void del(int x)
{
pcnt[cnt[x]]--;
cnt[x]--;
pcnt[cnt[x]]++;
}
inline void changx(int x,int ti)
{
if(c[ti].p>=q[x].l&&c[ti].p<=q[x].r){
del(col[c[ti].p]);
add(c[ti].col);
}
swap(col[c[ti].p],c[ti].col);
}
int main(void)
{
int cmd;
scanf("%d%d",&n,&m);
nm = pow(n,2.0/3);
for(int i=1;i<=n;i++){
scanf("%d",&col[i]);
pcol[tot++] = col[i];
}
for(int i=1;i<=m;i++){
scanf("%d%d%d",&cmd,&x,&y);
if(cmd==1){
cntq++;
q[cntq].id = cntq;
q[cntq].l = x;q[cntq].r = y;
q[cntq].t = cntc;
}
else{
cntc++;
c[cntc].p = x;c[cntc].col = y;
pcol[tot++] = y;
}
}
sort(pcol,pcol+tot);
tot = unique(pcol,pcol+tot)-pcol;
for(int i=1;i<=n;i++){
col[i] = lower_bound(pcol,pcol+tot,col[i]) - pcol;
}
for(int i=1;i<=cntc;i++){
c[i].col = lower_bound(pcol,pcol+tot,c[i].col) - pcol;
}
sort(q+1,q+cntq+1);
for(int i=1;i<=cntq;i++){
while(l>q[i].l)
add(col[--l]);
while(r<q[i].r)
add(col[++r]);
while(l<q[i].l)
del(col[l++]);
while(r>q[i].r)
del(col[r--]);
while(now<q[i].t)
changx(i,++now);
while(now>q[i].t)
changx(i,now--);
for(ans[q[i].id]=1;pcnt[ans[q[i].id]]>0;++ans[q[i].id]);
}
for(int i=1;i<=cntq;i++){
printf("%d\n",ans[i]);
}
return 0;
}
边栏推荐
- Order based evaluation index (especially for recommendation system and multi label learning)
- ie7设置overflow属性失效解决方法
- C managed and unmanaged
- Zxing simplified version, reprinted
- Process32first returns false, error x message 24
- copyTo
- 附加到进程之后,断点显示“当前不会命中断点 还没有为该文档加载任何符号”
- Jmeter配置元件之CSV数据文件设置
- Force deduction brush questions, sum of three numbers
- csdn空格用什么表示
猜你喜欢
arcgis的基本使用1
Your login IP is not within the login mask configured by the administrator
PMM(Percona Monitoring and Management )安装记录
Does volatile rely on the MESI protocol to solve the visibility problem? (top)
注册模块用例编写
Zipkin installation and use
mysql5.7.25主从复制(单向)
csdn空格用什么表示
arc-gis的基本使用2
配置ADCS后访问certsrv的问题
随机推荐
Calling DLL to start thread
arc-gis基础操作3
调用DLL开启线程的问题
nodejs中mysql的使用
Drawing shadow error diagram with MATLAB
添加dll
正则表达式
The provincial government held a teleconference on safety precautions against high temperature weather across the province
Qt随手笔记(二)Edit控件及float,QString转化、
OFDM 十六讲- OFDM
大二上第二周学习笔记
2022 chemical automation control instrument operation certificate test question simulation test platform operation
Basic use of Arc GIS 2
arc-gis的基本使用2
微信小程序图片无法显示时显示默认图片
配置ADCS后访问certsrv的问题
Wechat applet avatarcropper avatar clipping
省政府召开全省高温天气安全防范工作电视电话会议
Custom password input box, no rounded corners
大二上第一周学习笔记