题目

支持区间加和区间查询第 \(k\) 小


分析

分块之后给每个整块排序,这样修改的时候整块打标记,散块直接分开把需要加的部分暴力加之后归并,就是 \(O(\sqrt{n})\) 的

查询的话,如果只有散块直接归并出结果,否则二分答案,加上小块合并成的整块,相当于是整体二分,就是 \(O(\sqrt{n}\log{a_i})\) 的

理论上块长取 \(\sqrt{n}\log{n}\) 实际上直接取根号更快


代码

#include <cstdio>
#include <cctype>
#include <algorithm>
#include <cmath>
using namespace std;
const int N=100011;
int n,Q,a[N],lazy[N],b[N],rk[N],rK[N],Rk[N],L[N],R[N],pos[N],bl,_l[N],_r[N],_mid[N];
int iut(){
int ans=0,f=1; char c=getchar();
while (!isdigit(c)) f=(c=='-')?-f:f,c=getchar();
while (isdigit(c)) ans=ans*10+c-48,c=getchar();
return ans*f;
}
void print(int ans){
if (ans<0) putchar('-'),ans=-ans;
if (ans>9) print(ans/10);
putchar(ans%10+48);
}
bool cmp(int x,int y){return a[x]<a[y];}
void rebuild(int x,int l,int r,int z){
Rk[0]=rK[0]=0;
for (int i=L[x];i<=R[x];++i)
if (l<=rk[i]&&rk[i]<=r) Rk[++Rk[0]]=rk[i],a[rk[i]]+=z;
else rK[++rK[0]]=rk[i];
int i1=1,j1=1,j=L[x];
while (i1<=Rk[0]&&j1<=rK[0])
if (a[Rk[i1]]<a[rK[j1]]) rk[j++]=Rk[i1++];
else rk[j++]=rK[j1++];
while (i1<=Rk[0]) rk[j++]=Rk[i1++];
while (j1<=rK[0]) rk[j++]=rK[j1++];
}
int main(){
n=iut(),Q=iut(),bl=sqrt(n);
for (int i=1;i<=n;++i) a[i]=iut(),pos[i]=(i-1)/bl+1,rk[i]=i;
for (int i=1;i<=n;++i) if (!L[pos[i]]) L[pos[i]]=i;
for (int i=n;i>=1;--i) if (!R[pos[i]]) R[pos[i]]=i;
for (int i=1;i<=pos[n];++i) sort(rk+L[i],rk+R[i]+1,cmp);
for (int i=1;i<=Q;++i){
int opt=iut(),l=iut(),r=iut(),z=iut();
if (opt==1){
if (r-l+1<z||z<=0){
print(-1),putchar(10);
continue;
}
int ans=-1;
if (pos[l]==pos[r]){
for (int j=L[pos[l]];j<=R[pos[r]]&&z;++j)
if (l<=rk[j]&&rk[j]<=r) ans=a[rk[j]]+lazy[pos[l]],--z;
print(ans),putchar(10);
}else{
Rk[0]=rK[0]=0;
for (int j=L[pos[l]];j<=R[pos[l]];++j)
if (rk[j]>=l) Rk[++Rk[0]]=a[rk[j]]+lazy[pos[l]];
for (int j=L[pos[r]];j<=R[pos[r]];++j)
if (rk[j]<=r) rK[++rK[0]]=a[rk[j]]+lazy[pos[r]];
int i1=1,j1=1,len=0;
while (i1<=Rk[0]&&j1<=rK[0])
if (Rk[i1]<rK[j1]) b[++len]=Rk[i1++];
else b[++len]=rK[j1++];
while (i1<=Rk[0]) b[++len]=Rk[i1++];
while (j1<=rK[0]) b[++len]=rK[j1++];
if (pos[l]+1==pos[r]) print(b[z]),putchar(10);
else{
int mn=b[1],mx=b[len],cnt=0;
for (int j=pos[l]+1;j<pos[r];++j){
mn=min(mn,a[rk[L[j]]]+lazy[j]);
mx=max(mx,a[rk[R[j]]]+lazy[j]);
_l[j]=L[j],_r[j]=R[j];
}
_l[0]=1,_r[0]=len;
while (mn<mx){
int mid=(0ll+mn+mx)>>1,_L,_R,CNT=cnt;
if (_l[0]<=_r[0]){
_L=_l[0]-1,_R=_r[0];
while (_L<_R){
int _MID=(_L+_R+1)>>1;
if (b[_MID]<=mid) _L=_MID;
else _R=_MID-1;
}
_mid[0]=_L,cnt+=_L-_l[0]+1;
}
for (int j=pos[l]+1;j<pos[r];++j)
if (_l[j]<=_r[j]){
_L=_l[j]-1,_R=_r[j];
while (_L<_R){
int _MID=(_L+_R+1)>>1;
if (a[rk[_MID]]+lazy[j]<=mid) _L=_MID;
else _R=_MID-1;
}
_mid[j]=_L,cnt+=_L-_l[j]+1;
}
if (cnt<z){
mn=mid+1;
if (_l[0]<=_r[0]) _l[0]=_mid[0]+1;
for (int j=pos[l]+1;j<pos[r];++j)
if (_l[j]<=_r[j]) _l[j]=_mid[j]+1;
}else{
mx=mid;
if (_l[0]<=_r[0]) _r[0]=_mid[0];
for (int j=pos[l]+1;j<pos[r];++j)
if (_l[j]<=_r[j]) _r[j]=_mid[j];
cnt=CNT;
}
}
print(mn),putchar(10);
}
}
}else{
if (pos[l]==pos[r]){
if (L[pos[l]]==l&&R[pos[r]]==r) lazy[pos[l]]+=z;
else rebuild(pos[l],l,r,z);
}
else{
if (l==L[pos[l]]) lazy[pos[l]]+=z;
else rebuild(pos[l],l,R[pos[l]],z);
if (r==R[pos[r]]) lazy[pos[r]]+=z;
else rebuild(pos[r],L[pos[r]],r,z);
for (int j=pos[l]+1;j<pos[r];++j) lazy[j]+=z;
}
}
}
return 0;
}

#分块,二分#洛谷 5356 [Ynoi2017] 由乃打扑克的更多相关文章

  1. 洛谷P5356 [Ynoi2017] 由乃打扑克

    题目 https://www.luogu.com.cn/problem/P5356 思路 由乃题,那么考虑分块(大雾,但确实分块是正解). 题面很清晰,就是求动态的区间第k小,支持区间加法操作. 根据 ...

  2. 洛谷P4344 脑洞治疗仪 [SHOI2015] 线段树+二分答案/分块

    !!!一道巨恶心的数据结构题,做完当场爆炸:) 首先,如果你用位运算的时候不小心<<打成>>了,你就可以像我一样陷入疯狂的死循环改半个小时 然后,如果你改出来之后忘记把陷入死循 ...

  3. 洛谷P4198 楼房重建 (分块)

    洛谷P4198 楼房重建 题目描述 小A的楼房外有一大片施工工地,工地上有N栋待建的楼房.每天,这片工地上的房子拆了又建.建了又拆.他经常无聊地看着窗外发呆,数自己能够看到多少栋房子. 为了简化问题, ...

  4. 洛谷P2402 奶牛隐藏(网络流,二分答案,Floyd)

    洛谷题目传送门 了解网络流和dinic算法请点这里(感谢SYCstudio) 题目 题目背景 这本是一个非常简单的问题,然而奶牛们由于下雨已经非常混乱,无法完成这一计算,于是这个任务就交给了你.(奶牛 ...

  5. 洛谷CF1071E Rain Protection(计算几何,闵可夫斯基和,凸包,二分答案)

    洛谷题目传送门 CF题目传送门 对于这题,我无力吐槽. 虽然式子还是不难想,做法也随便口胡,但是一些鬼畜边界情况就是判不对. 首先显然二分答案. 对于每一个雨滴,它出现的时刻我们的绳子必须落在它上面. ...

  6. 分数规划模板(洛谷P4377 [USACO18OPEN]Talent Show)(分数规划,二分答案,背包)

    分数规划是这样一个东西: 给定若干元素,每个元素有两个属性值\(a_i,b_i\),在满足题目要求的某些限制下选择若干元素并求出\(\frac{\sum a}{\sum b}\)的最大值. 如果没有限 ...

  7. 洛谷P1084 疫情控制(NOIP2012)(二分答案,贪心,树形DP)

    洛谷题目传送门 费了几个小时杠掉此题,如果不是那水水的数据的话,跟列队的难度真的是有得一比... 话说蒟蒻仔细翻了所有的题解,发现巨佬写的都是倍增,复杂度是\(O(n\log n\log nw)\)的 ...

  8. 洛谷 [USACO17OPEN]Bovine Genomics G奶牛基因组(金) ———— 1道骗人的二分+trie树(其实是差分算法)

    题目 :Bovine Genomics G奶牛基因组 传送门: 洛谷P3667 题目描述 Farmer John owns NN cows with spots and NN cows without ...

  9. 洛谷P4117 [Ynoi2018]五彩斑斓的世界 [分块,并查集]

    洛谷 Codeforces 又是一道卡常题-- 思路 YNOI当然要分块啦. 分块之后怎么办? 零散块暴力,整块怎么办? 显然不能暴力改/查询所有的.考虑把相同值的用并查集连在一起,这样修改时就只需要 ...

  10. 洛谷P4072 [SDOI2016]征途(带权二分,斜率优化)

    洛谷题目传送门 一开始肯定要把题目要求的式子给写出来 我们知道方差的公式\(s^2=\frac{\sum\limits_{i=1}^{m}(x_i-\overline x)^2}{m}\) 题目要乘\ ...

随机推荐

  1. pikachu php反序列化漏洞

    原理 php中serialize(),unserialize()这两个函数. 序列化serialize() 序列化说通俗点就是把一个对象变成可以传输的字符串,比如下面是一个对象: class S{ p ...

  2. Hi3516开发笔记(十一):通过HiTools使用网口将uboot、kernel、roofts烧写进eMMC

    前言   前面烧写一直时烧写进入flush,是按照分区烧写.定制的板子挂的是eMMC,前面的烧写步骤一致,但是在烧写目标则时烧写eMMC了.  重新走一遍从无到有通过网口刷定制板卡的uboot.ker ...

  3. 正则函数及面向对象开发初识---day19

    1.正则函数 # ### 正则函数 import re #search 通过正则匹配出第一个对象返回,通过group取出对象中的值 strvar = "1+2 3*4" obj = ...

  4. React 组件之样式

    无论你的梦想有多么高远,记住,一切皆有可能. 我们从前面的学习知道一个 React 组件不仅仅只包含 DOM 结构的,还应该样式和 Javascript 逻辑的.这里我们学习下如何构建 CSS 样式. ...

  5. 前端面试题(四)—— 事件委托(Event Delegation)

    一.什么是事件委托 事件委托(Event Delegation)是一种常用的技术. 它利用事件冒泡的特性,在父元素上监听事件,而不是在子元素上直接添加事件监听器. 通过在父元素上捕获事件,然后根据事件 ...

  6. 【Azure 应用服务】Azure App Service (Windows) 使用Flask框架部署Python应用,如何在代码中访问静态文件呢?如何设置文件路径?是相对路径还是绝对路径呢?

    问题描述 使用Flask框架部署Python代码,如何访问其中的静态文件呢?如static问价夹中的图像资源,同时如何在代码中读取txt文件中的内容呢?是相对路径或者是绝对路径呢? 实验步骤 在App ...

  7. 【Azure 微服务】面对Service Fabric中节点状态不正常(Disabling/Warning/RemoveNode)的几种尝试解决方案

    问题描述 发现 Service Fabric 的节点状态异常,如出现 Disabling, Warning,或者 RemoveNode的情况,并且持续很长时间都没有变化(2小时以上).如何来缓解这种问 ...

  8. STL-vector模拟实现

    #pragma once #include<assert.h> #include<iostream> using std::cout; using std::endl; usi ...

  9. vm 虚拟机总是蓝屏 移除打印机和声卡 移除这俩硬件 (大文件用飞秋传输)

    vm 虚拟机总是蓝屏 移除打印机和声卡 移除这俩硬件 (大文件用飞秋传输)

  10. win10 有 休眠 功能,将内存保存到文件,开机10秒左右,恢复之前idea等所有软件

    休眠 休眠 休眠 重要的事情说三遍. 提示,默认不显示,需要控制面板 电源里面设置下.