[LOJ2736] [JOISC 2016 Day 3] 回转寿司 (分块+堆)
[LOJ2736] [JOISC 2016 Day 3] 回转寿司 (分块+堆)
题面
给出一个有n 个点的环,环上各点有一个初始权值 \(a_i\)
给出 Q 个询问,每次询问给出一个区间 [l,r]和一个值 A,对于 A 的变动定义如下
for (int i = l; i <= r; i++) if(a[i] > A) swap(a[i],A);
对于每个询问,回答遍历完区间[l,r]后 A的最终值。
分析
这种交换看起来很难用一般的数据结构维护,考虑对序列分块。
首先,我们发现如果一个块里面所有的数都<A,那么什么变化都不会发生。否则每个块中最大的数会被A替换掉,A变成\(max(A,max(a_i)) (i\in [l,r])\)。因此对每个块内的数维护一个大根堆,只有堆顶比当前A小的时候才会整块修改。
一般分块的套路,整块修改的时候只需要打一个标记,两端的小块直接按题面模拟遍历即可。遍历两端的时候要把标记下推,同时重构两端的块
考虑标记下推,我们发现对于两个不同的标记Ax,Ay,若Ax<Ay,最大的数会被替换成Ax。所以我们每个块用一个小根堆存储标记,遍历重构的块的时候若a[i]>A,把原来的a[i]插入小根堆,然后swap(A,a[i])。可以证明,这和多次遍历块来交换每个标记是一样的。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define maxn 400000
#define maxb 1000
using namespace std;
inline void qread(int &x) {
x=0;
int sign=1;
char c=getchar();
while(c<'0'||c>'9') {
if(c=='-') sign=-1;
c=getchar();
}
while(c>='0'&&c<='9') {
x=x*10+c-'0';
c=getchar();
}
x=x*sign;
}
inline void qprint(int x) {
if(x<0) {
putchar('-');
qprint(-x);
} else if(x==0) {
putchar('0');
return;
} else {
if(x>=10) qprint(x/10);
putchar('0'+x%10);
}
}
int n,m;
int a[maxn+5];
int bsz;
int bel[maxn+5];
inline int lb(int id){
return bsz*(id-1)+1;
}
inline int rb(int id){
return bsz*id>=n?n:bsz*id;
}
priority_queue<int>num[maxb+5];//大根堆,存储每一块中的数
priority_queue<int,vector<int>,greater<int> >mark[maxb+5] ;//小根堆,存储每一个块上替换标记
//从小到大是因为序列中的数会被优先换成小的标记
void rebuild(int id){//重构每个块,不管是整块替换还是部分替换,都要调用rebuild
while(!num[id].empty()) num[id].pop();
for(int i=lb(id);i<=rb(id);i++){
num[id].push(a[i]);
}
}
void push_down(int id){
if(!mark[id].empty()){
for(int i=lb(id);i<=rb(id);i++){
int v=mark[id].top();
if(v<a[i]){
swap(a[i],v);
mark[id].pop();
mark[id].push(v);//把a[i]与v交换
}
}
while(!mark[id].empty()) mark[id].pop();
rebuild(id);
}
}
int update(int l,int r,int A){
push_down(bel[l]);//非整块操作,必须下推标记
for(int i=l;i<=min(r,rb(bel[l]));i++){
if(A<a[i]) swap(a[i],A);
}
rebuild(bel[l]);
for(int i=bel[l]+1;i<bel[r];i++){
int v=num[i].top();
if(v>A){ //如果最大值比A小,就不替换了
num[i].pop();
num[i].push(A);
mark[i].push(A);
swap(A,v);
//整块修改的时候只需要替换最大值,剩下的操作push_down的时候完成
}
}
if(bel[l]!=bel[r]){
push_down(bel[r]);
for(int i=lb(bel[r]);i<=r;i++){
if(A<a[i]) swap(a[i],A);
}
rebuild(bel[r]);
}
return A;
}
int main(){
int l,r,A;
qread(n);
qread(m);
for(int i=1;i<=n;i++) qread(a[i]);
bsz=sqrt(n);
for(int i=1;i<=n;i++){
bel[i]=(i-1)/bsz+1;
num[bel[i]].push(a[i]);
}
for(int i=1;i<=m;i++){
qread(l);
qread(r);
qread(A);
if(l<=r){
A=update(l,r,A);
}else{
A=update(l,n,A);
A=update(1,r,A);
}
// printf("db:");
qprint(A);
putchar('\n');
}
}
[LOJ2736] [JOISC 2016 Day 3] 回转寿司 (分块+堆)的更多相关文章
- BZOJ_4627_[BeiJing2016]回转寿司_离散化+树状数组
BZOJ_4627_[BeiJing2016]回转寿司_离散化+树状数组 Description 酷爱日料的小Z经常光顾学校东门外的回转寿司店.在这里,一盘盘寿司通过传送带依次呈现在小Z眼前.不同的寿 ...
- Loj #2731 「JOISC 2016 Day 1」棋盘游戏
Loj 2731 「JOISC 2016 Day 1」棋盘游戏 JOI 君有一个棋盘,棋盘上有 \(N\) 行 \(3\) 列 的格子.JOI 君有若干棋子,并想用它们来玩一个游戏.初始状态棋盘上至少 ...
- bzoj 4627: [BeiJing2016]回转寿司 -- 权值线段树
4627: [BeiJing2016]回转寿司 Time Limit: 10 Sec Memory Limit: 256 MB Description 酷爱日料的小Z经常光顾学校东门外的回转寿司店. ...
- bzoj 4627: [BeiJing2016]回转寿司
4627: [BeiJing2016]回转寿司 Description 酷爱日料的小Z经常光顾学校东门外的回转寿司店.在这里,一盘盘寿司通过传送带依次呈现在小Z眼前.不同的寿 司带给小Z的味觉感受是不 ...
- 【BZOJ4627】[BeiJing2016]回转寿司 SBT
[BZOJ4627][BeiJing2016]回转寿司 Description 酷爱日料的小Z经常光顾学校东门外的回转寿司店.在这里,一盘盘寿司通过传送带依次呈现在小Z眼前.不同的寿司带给小Z的味觉感 ...
- K - 回转寿司(值域段数(板题) + 动态开点)
回转寿司 Description 酷爱日料的小Z经常光顾学校东门外的回转寿司店.在这里,一盘盘寿司通过传送带依次呈现在小Z眼前.不同的寿 司带给小Z的味觉感受是不一样的,我们定义小Z对每盘寿司都有一个 ...
- 「JOISC 2016 Day 1」棋盘游戏
「JOISC 2016 Day 1」棋盘游戏 先判无解:第1,3行有连续的空格或四个角有空格. 然后可以发现有解的情况第1,3行可以在任意时间摆放. 对于某一列,若第2行放有棋子,那么显然可以把棋盘分 ...
- LOJ 2736 「JOISC 2016 Day 3」回转寿司 ——堆+分块思路
题目:https://loj.ac/problem/2736 如果每个询问都是 l = 1 , r = n ,那么每次输出序列的 n 个数与本次操作的数的最大值即可.可以用堆维护. 不同区间的询问,可 ...
- 「JOISC 2016 Day 3」回转寿司
https://loj.ac/problem/2736 题解 挺有意思的题. 考虑这种操作不好直接维护,还有时限比较长,所以考虑分块. 考虑一个操作对整个块的影响,无非就是可能把最大的拿走,再把新的元 ...
随机推荐
- 组件通信 Provide&&inject
在父组件中利用Provide 注入数据,在所有的子组件都可以拿到这个数据 可以在vue 中用来刷新页面 <!DOCTYPE html> <html lang="en&quo ...
- Textarea随着文本的字数自适应高度,后来发现用 contenteditable 代替textarea 效果更佳
做移动端项目遇到很多问题,最近比如textarea 随着文本的字数自动撑开高度, 网上也查阅了一些资料发现比较有用的方法 就是获取 textarea的行数和换行符来动态改变textarea的高度 就 ...
- MySQL基础day03 存储引擎和外键MySQL 5.6
MySQL基础day03_存储引擎和外键-MySQL 5.6 外键的条件: 1,表的存储引擎为innodb存储引擎 2,表中外键字段的类型要与参考表的字段类型一致 3,外键字段要是索引类型中的一种 M ...
- 匿名函数 python内置方法(max/min/filter/map/sorted/reduce)面向过程编程
目录 函数进阶三 1. 匿名函数 1. 什么是匿名函数 2. 匿名函数的语法 3. 能和匿名函数联用的一些方法 2. python解释器内置方法 3. 异常处理 面向过程编程 函数进阶三 1. 匿名函 ...
- CF1244C
题目描述 给出n,p,w,d,求(x,y,z)使得 xw+yd=p x+y+z=n 其中d<w<10^5^ 题解 显然扩欧啊( 来自天国的long long y如果大于等于w,则显然可以把 ...
- JavaScript性能优化之小知识总结
1.避免全局查找 在一个函数中会用到全局对象存储为局部变量来减少全局查找,因为访问局部变量的速度要比访问全局变量的速度更快些 2.定时器 如果针对的是不断运行的代码,不应该使用setTimeout,而 ...
- 【CF1247E】Rock Is Push(DP,二分)
题意:有一个n*m的方格,每一格可能为空也可能有石头,要从(1,1)走到(n,m),每次可以往右或往下走 每次走的时候都会将自己面前的所有石头向移动方向推一格,如果碰到了边界就推不过去 问方案数模1e ...
- 【HDOJ6731】Angle Beats(极角排序)
题意:二维平面上给定n个整点,q个询问 每个询问给定另外的一个整点,问其能与n个整点中任意取2个组成的直角三角形的个数 保证所有点位置不同 n<=2e3,q<=2e3,abs(x[i],y ...
- C. Almost Equal
C. Almost Equal n个数字全排成一个圈,满足任意相邻n个之和之间最大最小值之差不超过1 n为偶数时 不存在 n为奇数,构造 #include<bits/stdc++.h> u ...
- css内容过长显示省略号的几种解决方法
单行文本(方法一): 语法: text-overflow : clip | ellipsis 参数: clip : 不显示省略标记(...),而是简单的裁切 (clip这个参数是不常用的!) elli ...