题面


样例输入

5 8
1 1 4 2
2 3 1
2 3 3
1 2 5 1
2 3 3
2 5 2
2 1 2
2 1 3

样例输出

1
0
4
0
1
0

样例解释

题解

这道题简单了不知多少倍。

我们可以把所有询问操作放到最后,计算出答案之后,再判断每个询问的答案是否超出原本限制,超过了就输出 0 。

把询问跟操作分开后,整体二分就行了。知道整体二分的基本都应该想到怎么做了吧:

所有操作按照原序(混凝土种类从小到大),所有询问按照

x

x

x 从小到大排。

递归到操作区间

[

l

,

r

]

[l,r]

[l,r] 、同时对应询问区间

[

l

2

,

r

2

]

[l_2,r_2]

[l2​,r2​] 时,定操作区间的中点为

m

i

d

=

l

+

r

2

{\rm mid} = \lfloor\frac{l+r}{2}\rfloor

mid=⌊2l+r​⌋ 。我们把一个操作看成是两个二元组 (l,h)(r+1,-h) ,表示把

[

l

,

+

]

[{\rm l},+\infty]

[l,+∞] 的区域整体加

h

h

h,同时把

[

r

,

+

]

[{\rm r},+\infty]

[r,+∞] 的区域整体加

h

-h

−h 。

我们处理出操作区间

[

l

,

m

i

d

]

[l,{\rm mid}]

[l,mid] 内的所有二元组按照第一个元素从小到大排序后的序列

s

t

st

st ,然后一边遍历询问区间

[

l

2

,

r

2

]

[l_2,r_2]

[l2​,r2​] ,一边用扫描线扫描序列

s

t

st

st ,得到所有操作在当前询问位置

x

i

x_i

xi​ 处累计的高度,若该高度大于等于

y

i

y_i

yi​ ,说明该询问的答案在操作

[

l

,

m

i

d

]

[l,{\rm mid}]

[l,mid] 里,把该询问扔进“左儿子询问区间”,否则扔进“右儿子询问区间”。由于询问位置是递增的,二元组首元素也是递增的,因此这个过程是线性的。

我们把

[

l

2

,

r

2

]

[l_2,r_2]

[l2​,r2​] 的询问分流后,用“左儿子询问区间”替换

[

l

2

,

m

d

]

[l_2,md]

[l2​,md] ,“右儿子询问区间”替换

[

m

d

+

1

,

r

2

]

[md+1,r_2]

[md+1,r2​] ,接下来递归

(

[

l

,

m

i

d

]

,

[

l

2

,

m

d

]

)

\Big([l,{\rm mid}],[l_2,md]\Big)

([l,mid],[l2​,md]) 和

(

[

m

i

d

+

1

,

r

]

,

[

m

d

+

1

,

r

2

]

)

\Big([{\rm mid}+1,r],[md+1,r_2]\Big)

([mid+1,r],[md+1,r2​]) 。

于是我们的算法瓶颈就在二元组序列

s

t

st

st 的处理上,目前仍需要排序,使得整个程序复杂度是

O

(

q

log

2

q

)

O(q\log^2q)

O(qlog2q) 的。我们需要砍掉一个

log

q

\log q

logq。

我们发现,一个操作的两个二元组是恒定的,于是,可以一开始就将所有二元组排序,形成序列

S

T

ST

ST ,然后操作中的

s

t

st

st 可以通过

S

T

ST

ST 的子串类似询问区间的分流得到。我们再多两个参数

l

3

,

r

3

l_3,r_3

l3​,r3​ ,表示当前操作区间对应的二元组(子)序列

[

l

3

,

r

3

]

[l_3,r_3]

[l3​,r3​] ,然后扫描所有二元组,把来源种类小于等于

m

i

d

{\rm mid}

mid 的二元组归到“左序列”中,其余归到“右序列”,然后合并形成新序列,替换

[

l

3

,

r

3

]

[l_3,r_3]

[l3​,r3​]。设分界点为

m

i

mi

mi ,

[

l

3

,

m

i

]

[l_3,mi]

[l3​,mi] 和

[

m

i

+

1

,

r

3

]

[mi+1,r_3]

[mi+1,r3​] 里的二元组是排好序的,而且这个分流也是线性的。我们要用的

s

t

st

st 就是这时候的子序列

[

l

3

,

m

i

]

[l_3,mi]

[l3​,mi] 。

时间复杂度

O

(

q

log

q

)

O(q\log q)

O(qlogq) 。

CODE

#include<set>
#include<map>
#include<queue>
#include<stack>
#include<random>
#include<vector>
#include<bitset>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define MAXN 1000005
#define LL long long
#define ULL unsigned long long
#define DB double
#define lowbit(x) (-(x) & (x))
#define ENDL putchar('\n')
#define FI first
#define SE second
LL read() {
LL f=1,x=0;int s = getchar();
while(s < '0' || s > '9') {if(s<0)return -1;if(s=='-')f=-f;s = getchar();}
while(s >= '0' && s <= '9') {x = (x<<3) + (x<<1) + (s^48); s = getchar();}
return f*x;
}
void putpos(LL x) {if(!x)return ;putpos(x/10);putchar('0'+(x%10));}
void putnum(LL x) {
if(!x) {putchar('0');return ;}
if(x<0) {putchar('-');x = -x;}
return putpos(x);
}
void AIput(LL x,int c) {putnum(x);putchar(c);} int n,m,s,o,k;
int L[MAXN],R[MAXN],H[MAXN],X[MAXN],cna;
struct it{
int x,id;
LL y;
it(){x=y=id=0;}
it(int X,LL Y,int I){x=X;y=Y;id=I;}
}q[MAXN],q1[MAXN],q2[MAXN];
it st[MAXN<<1],s1[MAXN<<1],s2[MAXN<<1];
int tp;
int as[MAXN],lm[MAXN],cnq;
bool cmpq(it a,it b) {return a.x < b.x;}
void solve(int l,int r,int l2,int r2,int l3,int r3) {
if(l == r) {
int ll = L[l],rr = R[l],h = H[l];
for(int i = l2;i <= r2;i ++) {
if(ll <= q[i].x && rr >= q[i].x && h >= q[i].y) {
as[q[i].id] = X[l];
}
}return ;
}
int mid = (l + r) >> 1;
int ct1 = 0,ct2 = 0;
for(int i = l3;i <= r3;i ++) {
if(st[i].id <= mid) s1[++ ct1] = st[i];
else s2[++ ct2] = st[i];
}
int md = l3 + ct1 - 1;
for(int i = l3;i <= md;i ++) st[i] = s1[i-l3+1];
for(int i = md+1;i <= r3;i ++) st[i] = s2[i-md];
int j = l3,c1 = 0,c2 = 0;
LL sm = 0;
for(int i = l2;i <= r2;i ++) {
int xx = q[i].x;
while(j <= md && st[j].x <= xx) sm += st[j ++].y;
if(q[i].y <= sm) {
q1[++ c1] = q[i];
}
else {
q[i].y -= sm;
q2[++ c2] = q[i];
}
}
int md2 = l2 + c1 - 1;
for(int i = l2;i <= md2;i ++) q[i] = q1[i-l2+1];
for(int i = md2+1;i <= r2;i ++)q[i] = q2[i-md2];
solve(l,mid,l2,md2,l3,md);
solve(mid+1,r,md2+1,r2,md+1,r3);
return ;
}
int main() {
freopen("concrete.in","r",stdin);
freopen("concrete.out","w",stdout);
n = read();m = read();
for(int i = 1;i <= m;i ++) {
k = read();
if(k == 1) {
cna ++;
L[cna] = read();
R[cna] = read();
H[cna] = read();
X[cna] = i;
st[++ tp] = it(L[cna],H[cna],cna);
st[++ tp] = it(R[cna]+1,-H[cna],cna);
}
else {
cnq ++;
q[cnq].x = read();
q[cnq].y = read();
q[cnq].id = cnq;
lm[cnq] = i;
}
}
sort(st + 1,st + 1 + tp,cmpq);
sort(q + 1,q + 1 + cnq,cmpq);
solve(1,cna,1,cnq,1,tp);
for(int i = 1;i <= cnq;i ++) {
if(!as[i] || as[i] > lm[i]) {
AIput(0,'\n');
}
else AIput(as[i],'\n');
}
return 0;
}

【NOI P模拟赛】混凝土粉末(整体二分)的更多相关文章

  1. [NOI P模拟赛] 传统艺能(子序列自动机、矩阵乘法,线段树)

    (2:00)OID:"完了,蓝屏了!"(代码全消失) 众人欢呼 OID:开机,"原题测试--" (30min later)OID 开始传统艺能: " ...

  2. 【XJOI】【NOI考前模拟赛7】

    DP+卡常数+高精度/  计算几何+二分+判区间交/  凸包 首先感谢徐老师的慷慨,让蒟蒻有幸膜拜了学军的神题.祝NOI2015圆满成功 同时膜拜碾压了蒟蒻的众神QAQ 填填填 我的DP比较逗比……( ...

  3. NOI.ac模拟赛20181021 ball sequence color

    T1 ball 可以发现每次推动球时,是将每个球的位置 −1-1−1 ,然后把最左边的球放到 P−1P-1P−1 处. 记个 −1-1−1 次数,再用set维护就好了. #include <bi ...

  4. NOI.ac 模拟赛20181103 排队 翘课 运气大战

    题解 排队 20% 1≤n≤20,1≤x,hi≤201\le n\le 20, 1\le x,h_i\le 201≤n≤20,1≤x,hi​≤20 随便暴力 50% 1≤n≤2000,1≤x,hi≤1 ...

  5. 9 16 模拟赛&关于线段树上二分总结

    1 考试时又犯了一个致命的错误,没有去思考T2的正解而是去简单的推了一下式子开始了漫漫找规律之路,不应该这样做的 为了得到规律虽然也打了暴力 但是还是打了一些不必要的程序 例如求组合数什么的比较浪费时 ...

  6. 【NOI P模拟赛】奶油蛋糕塔(状压 DP)

    题面 数据范围 1 ≤ n ≤ 5 × 1 0 5 1\leq n\leq5\times10^5 1≤n≤5×105 . 题解 n ≤ 20 n\leq 20 n≤20 的状压应该都会吧,状态记录已经 ...

  7. 【NOI P模拟赛】最短路(树形DP,树的直径)

    题面 给定一棵 n n n 个结点的无根树,每条边的边权均为 1 1 1 . 树上标记有 m m m 个互不相同的关键点,小 A \tt A A 会在这 m m m 个点中等概率随机地选择 k k k ...

  8. noi.acNOIP模拟赛5-count

    题目链接 戳我 题意简述 你有一个n+1个数的序列,都是1~n,其中只有一个有重复,求每个长度的本质不同的子序列个数.\(mod 1e9+7\). sol 说起来也很简单,设相同的数出现的位置为\(l ...

  9. 2018/3/13 noiρ[rəʊ]模拟赛 125分

    T1 60分暴力,水分也不会水,打表也不会打,正解是不可能写正解的,这辈子都写不出来正解的,虽然是zz题但是也拿不到分这样子. 正解:(啥?正解是sb组合数?这都他娘的想不到,真鸡儿丢人我自杀吧.) ...

随机推荐

  1. 1.数据结构《Pytorch神经网络高效入门教程》Deeplizard

    当移动一个数组或向量时,我们需要一个索引:二维数组/矩阵需要两个索引, 比如说标量是零维张量,数组/向量/矢量是一维张量,矩阵是是二维张量,n维数组是n维张量. 如果我们被告知,  假设有一个张量t, ...

  2. 155_模型_Power BI & Power Pivot 进销存之安全库存

    155_模型_Power BI & Power Pivot 进销存之安全库存 一.背景 谈进销存的概念时,我们也需要提及另外一个概念:安全库存. 库存周转在理想的状态下是做到零库存,但是在内部 ...

  3. 【动态规划】统计蚂蚁 (ants)

    题目 描述 蚂蚁山上有T(1<=T<=1,000)种蚂蚁,标记为1..T,每种蚂蚁有N_i只蚂蚁(1<=N_i<=100),现有A(A<=5000)只蚂蚁,从中选出S,S ...

  4. UiPath屏幕抓取Screen Scraping的介绍和使用

    一.屏幕抓取(Screen Scraping)的介绍 屏幕抓取使您能够在特定的UI元素或文档(如.PDF文档)中提取数据 二.屏幕抓取(Screen Scraping)在UiPath中的使用 [if ...

  5. GameFramework食用指南

    1.框架简介 GF框架分两部分,GameFramework(GF)和UnityGameFramework(UGF): 通过接口的形式对Unity引擎进行了解耦: GF独立于Unity,具体业务逻辑实现 ...

  6. ClickHouse(03)ClickHouse怎么安装和部署

    本文会介绍如何安装和部署ClickHouse,官方推荐的几种安装模式,以及安装之后如何启动,ClickHouse集群如何配置等. 简单来说,ClickHouse的搭建流程如下: 环境检查,环境依赖安装 ...

  7. labview从入门到出家7(进阶篇)--队列的使用

    本节简单讲解队列在Labview中的使用,队列你可以认为就是一组先进先出的数据列表,在Labview中常用来缓存和传递数据.用了这么久的队列,个人认为有个方便的地方在于数据传递的把控,不管是局部变量还 ...

  8. GDOI 2022 普及组游记

    To LuoguDAY -1 期中考成绩下来了,全无了除了历史 (96) 和生物 (95) 还能看,剩下的-,语文 101.5 ,少错一道选择和断句就 107.5 了,居然比雌兔还低 数学少错一道选择 ...

  9. Linux串口编程进阶

    在<Linux串口编程>编程一文中介绍了串口应用中常用的基本操作,如:串口打开关闭.串口设置.数据收发等.本篇文章主要基于常规串口操作进行了扩充,主要介绍如下操作: Linux系统使用非标 ...

  10. linux 安装redis及问题收集

    contos 7 下安装redis教程可参照https://www.cnblogs.com/hxun/p/11075755.html值得注意的是在第6步方法一(所以建议使用方法二),如果直接使用xft ...