题目

支持区间加和区间查询第 \(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. PostgreSQL中查看版本的几种方式

    PostgreSQL中查看版本的几种方式 1.SQL方式 1 2 3 4 5 6 7 8 9 10 postgres=# show server_version;  server_version -- ...

  2. 【LeetCode栈与队列#01】队列的基本操作:用栈模拟队列和用队列模拟栈

    用栈实现队列 力扣题目链接(opens new window) 使用栈实现队列的下列操作: push(x) -- 将一个元素放入队列的尾部. pop() -- 从队列首部移除元素. peek() -- ...

  3. 有了这份Java面试中的葵花宝典,让你面试起飞!!!

    HashMap面试题 HashMap与HashTable的区别 1.HashMap线程不安全 HashTable 线程是安全的采用synchronized 2.HashMap允许存放key 为null ...

  4. 【Azure 事件中心】EventHub 中同一条消息不停的推送给消费端问题记录

    问题描述 EventHub 中同一条消息,不停的推送给消费端,查看日志发现错误: Caused by: com.azure.messaging.eventhubs.implementation.Par ...

  5. BIGO 的数据管理与应用实践

    本文首发于 Nebula Graph Community 公众号 本文整理自 BIGO 在 nMeetp 上的主题分享,主要介绍 BIGO 过去一年在数据管理建设方面的理解和探索.而 BIGO 数据管 ...

  6. flutter3-winchat桌面端聊天实例|Flutter3+Dart3+Getx仿微信Exe程序

    首发原创flutter3+bitsdojo_window+getx客户端仿微信exe聊天Flutter-WinChat. flutter3-dart3-winchat 基于flutter3+dart3 ...

  7. STL-queue模拟实现

    #include<list> #include<assert.h> #include<deque> #include<iostream> using s ...

  8. linux下查看文件时显示行号

    1.用 vi 或 vim 打开文件后显示行号: 显示当前行号: :nu 显示所有行号: :set nu     2.设置服务器显示行号 2.1:编辑~/.vimrc文件,在该文件中加入         ...

  9. Zabbix6.0使用教程 (五)—zabbix从二进制包安装上篇

    大家好,我是乐乐.上一期我们已经讲过从源代码安装zabbix,本期着重讲从二进制包安装zabbix. 当我们在ZABBIX官方存储库可以看到,Zabbix SIA 提供如下官方RPM和DEB包: ·R ...

  10. 一文搞懂Vue的MVVM模式与双向绑定

    v-model 是 Vue.js 框架中用于实现双向数据绑定的指令.它充分体现了 MVVM(Model-View-ViewModel)模式中的双向数据绑定特性.下面我们将详细解释 v-model 如何 ...