Codeforces 题目传送门 & 洛谷题目传送门

震惊!我竟然独立切掉了这道 *3100 的题!

虽然此题难度的确虚高,感觉真实评分也就 2800~2900 罢。但感觉还是挺有成就感的(

注意到题目中所询问的那坨东西基于每个数在区间中出现的次数,因此此题必不可少的一个步骤就是求出每个数的出现次数 \(cnt_x\),这个可以用带修莫队在 \(n^{5/3}\) 的时间内求出,这里就不再赘述了。

接下来考虑怎样计算答案,这也是本题的难点所在。我们将所有 \([l,r]\) 中出现次数非零的数的出现次数从小到大排序,设为 \(x_1,x_2,\cdots,x_m\),显然我们选择的数在 \(x\) 序列中一定是一段连续的区间 \(x_i,x_{i+1},\cdots,x_{i+k-1}\),故答案为 \(\min\limits_{i=1}^{m-k+1}x_{i+k-1}-x_i\)。

暴力排序求解显然是不行的,但是注意到 \(x\) 数组有一个非常重要的性质,就是 \(\sum\limits_{i=1}^mx_i=r-l+1\le n\),我们不妨设一个阈值 \(B\),我们考虑以下两个暴力:

  • 对于 \(x_{i+k-1}\le B\) 的 \(i\),我们开一个桶 \(cnt\_cnt_i\) 表示 \(\sum[x_j=i]\),也就是 \(x_j=i\) 的个数,然后枚举 \(x_i\),用 two pointers 找出最小的 \(r\) 使得 \(\sum\limits_{j=i}^rcnt\_cnt_j\ge k\) 并用 \(r-i\) 更新答案。
  • 对于 \(x_{i+k-1}>B\) 的 \(i\),注意到这样的 \(i\) 不超过 \(\lfloor\dfrac{n}{B}\rfloor\) 个,于是我们暴力找出 \(x_i>B\) 的 \(x_i\) 并将其从小到大排序,然后直接用 \(x_{i+k-1}-x_i\) 更新答案即可。复杂度 \(\dfrac{n}{B}\log\dfrac{n}{B}\)。

用均值不等式可知 \(B=\sqrt{n\log n}\) 时复杂度最优。

还有一个小问题,就是怎样求出 \(x_{i}>B\) 的 \(x_i\),一个很显然的思路是在莫队 push/pop 的过程中维护一个 set,如果当前加入的值的 \(cnt\ge B\) 就压入 set,否则从 set 中删除当前值,不过这样会使带修莫队的复杂度变为 \(n^{5/3}\log n\),无法通过。注意到如果 \(i\) 满足 \(i\) 从始至终在序列中出现的次数 \(<B\),那么它一定不可能出现在这个 set 中,故考虑预处理所有存在某个时刻在序列中出现次数 \(>B\) 的 \(i\)——这样的 \(i\) 必定不会超过 \(\dfrac{n}{B}\),然后每次询问时暴力在这样的 \(i\) 中查找出现次数 \(>B\) 的值,这样就能保证复杂度了。

时间复杂度 \(n^{5/3}+n\sqrt{n\log n}\)

还有一点是回滚莫队时间轴那一维是先更新再移动指针,我因此 WA 了好几发……

这个莫队板子题能放到 edu 的 G 就 nm 离谱

#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define fill0(a) memset(a,0,sizeof(a))
#define fill1(a) memset(a,-1,sizeof(a))
#define fillbig(a) memset(a,63,sizeof(a))
#define pb push_back
#define ppb pop_back
#define mp make_pair
template<typename T1,typename T2> void chkmin(T1 &x,T2 y){if(x>y) x=y;}
template<typename T1,typename T2> void chkmax(T1 &x,T2 y){if(x<y) x=y;}
typedef pair<int,int> pii;
typedef long long ll;
typedef unsigned int u32;
typedef unsigned long long u64;
namespace fastio{
#define FILE_SIZE 1<<23
char rbuf[FILE_SIZE],*p1=rbuf,*p2=rbuf,wbuf[FILE_SIZE],*p3=wbuf;
inline char getc(){return p1==p2&&(p2=(p1=rbuf)+fread(rbuf,1,FILE_SIZE,stdin),p1==p2)?-1:*p1++;}
inline void putc(char x){(*p3++=x);}
template<typename T> void read(T &x){
x=0;char c=getchar();T neg=0;
while(!isdigit(c)) neg|=!(c^'-'),c=getchar();
while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=getchar();
if(neg) x=(~x)+1;
}
template<typename T> void recursive_print(T x){if(!x) return;recursive_print(x/10);putc(x%10^48);}
template<typename T> void print(T x){if(!x) putc('0');if(x<0) putc('-'),x=~x+1;recursive_print(x);}
void print_final(){fwrite(wbuf,1,p3-wbuf,stdout);}
}
const int MAXN=1e5;
const int BLK_2_3=2000;
const int BLK_1_2=316;
const int INF=0x3f3f3f3f;
int n,qu,qk=0,a[MAXN+5],tot_cnt[MAXN+5],cnt[MAXN+5],cnt_cnt[MAXN+5];
int blk_cnt,L[MAXN+5],R[MAXN+5],bel[MAXN+5];
struct chg{int x,pre,cur;} c[MAXN+5];
vector<int> tot;
void push(int x){cnt_cnt[cnt[x]]--;cnt[x]++;cnt_cnt[cnt[x]]++;}
void pop(int x){cnt_cnt[cnt[x]]--;cnt[x]--;cnt_cnt[cnt[x]]++;}
struct query{
int l,r,k,id;
bool operator <(const query &rhs){
if(bel[l]!=bel[rhs.l]) return l<rhs.l;
else if(bel[r]!=bel[rhs.r]) return r<rhs.r;
return id<rhs.id;
}
} q[MAXN+5];
int ans[MAXN+5];
int deal(int k){
vector<int> over;int ret=INF;
for(int i=0;i<tot.size();i++) if(cnt[tot[i]]>BLK_1_2) over.pb(cnt[tot[i]]);
sort(over.begin(),over.end());
for(int l=1,r=1,sum=0;l<=BLK_1_2;l++){
while(r<=BLK_1_2&&sum<k) sum+=cnt_cnt[r],r++;
if(sum<k){
int need=k-sum;
if(need<=over.size()) chkmin(ret,over[need-1]-l);
} else chkmin(ret,r-l-1);
sum-=cnt_cnt[l];
}
for(int i=0;i+k-1<over.size();i++) chkmin(ret,over[i+k-1]-over[i]);
return ret;
}
int main(){
scanf("%d%d",&n,&qu);
for(int i=1;i<=n;i++) scanf("%d",&a[i]),tot_cnt[a[i]]++;
blk_cnt=(n-1)/BLK_2_3+1;
for(int i=1;i<=blk_cnt;i++){
L[i]=(i-1)*BLK_2_3+1;R[i]=min(i*BLK_2_3,n);
for(int j=L[i];j<=R[i];j++) bel[j]=i;
}
for(int i=1;i<=qu;i++){
int opt;scanf("%d",&opt);
if(opt==1){
qk++;scanf("%d%d%d",&q[qk].l,&q[qk].r,&q[qk].k);
q[qk].id=i;
} else {
scanf("%d%d",&c[i].x,&c[i].cur);
c[i].pre=a[c[i].x];a[c[i].x]=c[i].cur;
tot_cnt[c[i].cur]++;
}
} sort(q+1,q+qk+1);int cl=1,cr=0,ct=qu;
memset(ans,-1,sizeof(ans));
for(int i=1;i<=MAXN;i++) if(tot_cnt[i]>BLK_1_2) tot.pb(i);
for(int i=1;i<=qk;i++){
while(cr<q[i].r) push(a[++cr]);
while(cl>q[i].l) push(a[--cl]);
while(cr>q[i].r) pop(a[cr--]);
while(cl<q[i].l) pop(a[cl++]);
while(ct<q[i].id){
if(c[ct].x){
if(q[i].l<=c[ct].x&&c[ct].x<=q[i].r) pop(c[ct].pre);
a[c[ct].x]=c[ct].cur;
if(q[i].l<=c[ct].x&&c[ct].x<=q[i].r) push(c[ct].cur);
} ct++;
}
while(ct>q[i].id){
if(c[ct].x){
if(q[i].l<=c[ct].x&&c[ct].x<=q[i].r) pop(c[ct].cur);
a[c[ct].x]=c[ct].pre;
if(q[i].l<=c[ct].x&&c[ct].x<=q[i].r) push(c[ct].pre);
} ct--;
} ans[q[i].id]=deal(q[i].k);
}
for(int i=1;i<=qu;i++) if(~ans[i]) printf("%d\n",(ans[i]^INF)?ans[i]:-1);
return 0;
}
/*
12 11
2 1 1 2 1 1 3 2 1 1 3 3
1 2 10 3
1 2 11 3
2 7 2
1 3 9 2
1 1 12 1
1 1 12 4
2 12 4
1 1 12 4
2 1 5
1 3 12 2
1 1 4 3
*/
/*
10 2
1 2 2 1 1 3 1 1 3 1
1 3 8 2
1 3 8 3
*/

Codeforces 1476G - Minimum Difference(带修莫队+根号平衡)的更多相关文章

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

    3052: [wc2013]糖果公园 Time Limit: 200 Sec  Memory Limit: 512 MBSubmit: 883  Solved: 419[Submit][Status] ...

  2. 「洛谷1903」「BZOJ2120」「国家集训队」数颜色【带修莫队,树套树】

    题目链接 [BZOJ传送门] [洛谷传送门] 题目大意 单点修改,区间查询有多少种数字. 解法1--树套树 可以直接暴力树套树,我比较懒,不想写. 稍微口胡一下,可以直接来一个树状数组套主席树,也就是 ...

  3. BZOJ2120 数颜色 莫队 带修莫队

    原文链接https://www.cnblogs.com/zhouzhendong/p/BZOJ2120.html 题目传送门 - BZOJ2120 题意 给定一个长度为 $n$ 的序列 $a$ ,有 ...

  4. BZOJ3052/UOJ#58 [wc2013]糖果公园 莫队 带修莫队 树上莫队

    原文链接https://www.cnblogs.com/zhouzhendong/p/BZOJ3052.html 题目传送门 - BZOJ3052 题目传送门 - UOJ#58 题意 给定一棵树,有 ...

  5. UVA 12345 Dynamic len(带修莫队)

    Dynamic len [题目链接]Dynamic len [题目类型]带修莫队 &题解: 莫队可以单点更改,只要再多加一维,代表查询次数,排序的时候3个关键字. 之后循环离线的时候,先暴力时 ...

  6. bzoj 2120 数颜色 (带修莫队)

    题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=2120 题意:两种操作:Q 询问区间  l - r  内颜色的种类 ,R 单点修改 思路 ...

  7. BZOJ 4129 Haruna’s Breakfast (分块 + 带修莫队)

    4129: Haruna’s Breakfast Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 835  Solved: 409[Submit][St ...

  8. BZOJ 2120 数颜色 (带修莫队)

    2120: 数颜色 Time Limit: 6 Sec  Memory Limit: 259 MBSubmit: 6367  Solved: 2537[Submit][Status][Discuss] ...

  9. BZOJ3052: [wc2013]糖果公园【树上带修莫队】

    Description Input Output Sample Input Sample Input Sample Output 84 131 27 84 HINT 思路 非常模板的树上带修莫队 真的 ...

随机推荐

  1. 解决el-checkbox-group 的v-model无法绑定对象数组

    elementUI官方文档中el-checkbox-group组件绑定的都为一维数组,真实业务中数据绑定往往是多个键值对的对象数组,本文主要解决这个问题. 如下代码: <el-checkbox- ...

  2. java的加载与执行原理详解

    java程序从开发到最终运行经历了什么? (31) 编译期: 第一步:在硬盘某个位置(随意),新建一个xxx.java文件 第二步:使用记事本或者其他文本编辑器例如EditPlus打开xxx.java ...

  3. “介绍一下自己吧”——记2020BUAA软工团队介绍和采访

    写在前面 项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任建) 这个作业的要求在哪里 团队作业-团队介绍和采访 团队介绍 团队名称 我们是 BUAA软软软件工程小队 ,简称 ...

  4. [no code][scrum meeting] Alpha 7

    项目 内容 会议时间 2020-04-13 会议主题 OCR技术细节分析 会议时长 30min 参会人员 PM+OCR组成员 $( "#cnblogs_post_body" ).c ...

  5. RabbitMQ的一些理解和笔记

    在这篇博客中,简单记录一下 rabbitmq 服务器中一些基本的概念. Connection: connection 为 TCP连接,是我们的应用程序和RabbitMQ服务器真正发送和接收数据的地方. ...

  6. IDEA + maven 零基础构建 java agent 项目

    200316-IDEA + maven 零基础构建 java agent 项目 Java Agent(java 探针)虽说在 jdk1.5 之后就有了,但是对于绝大多数的业务开发 javaer 来说, ...

  7. 利用DMA实现采样数据的直接搬运存储

    尝试了下STM32的ADC采样,并利用DMA实现采样数据的直接搬运存储,这样就不用CPU去参与操作了. 找了不少例子参考,ADC和DMA的设置了解了个大概,并直接利用开发板来做一些实验来验证相关的操作 ...

  8. 面试官:熟悉JS中的new吗?能手写实现吗?

    目录 1 new 运算符简介 2 new 究竟干了什么事 3 模拟实现 new 运算符 4 补充 预备知识: 了解原型和原型链 了解this绑定 1 new 运算符简介 MDN文档:new 运算符创建 ...

  9. notepad++ 替换回车换行

    以" | "为分隔符,换行 结果如下图:

  10. Device /dev/sdb excluded by a filter

    原因是添加的磁盘是在另一个虚拟机中新建的,已经有了分区表,现在的虚拟机并不能识别磁盘的分区表,运行parted命令重做分区表,中途需要输入三次命令(mklabel msdos -> yes-&g ...