Loj 6279. 数列分块入门 3

Posted zjxxcn

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Loj 6279. 数列分块入门 3相关的知识,希望对你有一定的参考价值。

题目描述

给出一个长为 nnn 的数列,以及 nnn 个操作,操作涉及区间加法,询问区间内小于某个值 xxx 的前驱(比其小的最大元素)。

输入格式

第一行输入一个数字 nnn。

第二行输入 nnn 个数字,第 iii 个数字为 aia_iai?,以空格隔开。

接下来输入 nnn 行询问,每行输入四个数字 optmathrm{opt}opt、lll、rrr、ccc,以空格隔开。

若 opt=0mathrm{opt} = 0opt=0,表示将位于 [l,r][l, r][l,r] 的之间的数字都加 ccc。

若 opt=1mathrm{opt} = 1opt=1,表示询问 [l,r][l, r][l,r] 中 ccc 的前驱的值(不存在则输出 ?1-1?1)。

输出格式

对于每次询问,输出一行一个数字表示答案。

样例

样例输入

4
1 2 2 3
0 1 3 1
1 1 4 4
0 1 2 2
1 1 2 4

样例输出

3
-1

数据范围与提示

对于 100% 100\%100% 的数据,1≤n≤100000,?231≤others 1 leq n leq 100000, -2^{31} leq mathrm{others}1n100000,?231others、ans≤231?1 mathrm{ans} leq 2^{31}-1ans231?1。

 

思路: 同数列分块2,但是这里用set维护,时间复杂度O(n*sqrt(n)*logn)

技术分享图片
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define F(i,a,b) for(int i=a;i<=b;i++) 
 5 #define D(i,a,b) for(int i=a;i>=b;i--)
 6 #define ms(i,a)  memset(a,i,sizeof(a)) 
 7 #define LL       long long 
 8 #define st(x)    ((x-1)*B+1)
 9 #define ed(x)    min(x*B,n)
10 #define bl(x)    ((x-1)/B+1) 
11 
12 int inline read(){
13     int x=0,w=0; char c=getchar(); 
14     while (c<0 || c>9) w+=c==-,c=getchar(); 
15     while (c>=0 && c<=9) x=(x<<3)+(x<<1)+(c^48),c=getchar(); 
16     return w? -x: x;  
17 }
18 
19 int const maxn=100003;
20 LL  const inf=1LL<<50;  
21 
22 int n,B; 
23 LL a[maxn],add[400];  
24 multiset<LL> s[400];  
25 multiset<LL> :: iterator p;  
26 
27 void update(int l,int r,LL z){
28     int x=bl(l); 
29     int y=bl(r);  
30     if(x==y){
31         F(i,l,r) {
32             p=s[x].find(a[i]);  
33             s[x].erase(p); 
34             s[x].insert(a[i]+z) ;
35             a[i]+=z;  
36         }
37     }else {
38         F(i,l,ed(x)) {
39             p=s[x].find(a[i]);  
40             s[x].erase(p);  
41             s[x].insert(a[i]+z);  
42             a[i]+=z;  
43         }
44         F(i,st(y),r){
45             p=s[y].find(a[i]);  
46             s[y].erase(p); 
47             s[y].insert(a[i]+z);  
48             a[i]+=z;  
49         }
50         F(i,x+1,y-1) add[i]+=z;  
51     }
52 }
53 
54 LL query(int l,int r,LL z){
55     int x=bl(l); 
56     int y=bl(r);  
57     LL ans=-inf; 
58     if(x==y){
59         F(i,l,r) if(a[i]+add[x]<z) ans=max(ans,a[i]+add[x]);  
60     }else {
61         F(i,l,ed(x)) if(a[i]+add[x]<z) ans=max(ans,a[i]+add[x]);  
62         F(i,st(y),r) if(a[i]+add[y]<z) ans=max(ans,a[i]+add[y]); 
63         F(i,x+1,y-1) {
64             p=s[i].lower_bound(z-add[i]);  
65             if(p!=s[i].begin()) ans=max(ans,*(--p)+add[i]);  
66         }
67     }
68     return ans==-inf?  -1: ans;  
69 }
70 int main(){
71     n=read(); B=(int)sqrt(n);  
72     F(i,1,n) a[i]=read();
73     F(i,1,bl(n)) F(j,st(i),ed(i)) s[i].insert(a[j]); 
74     F(i,1,n){
75         int x=read(); 
76         int l=read(); 
77         int r=read(); 
78         int c=read(); 
79         if(x==0) update(l,r,c); 
80         else printf("%lld
",query(l,r,c)); 
81     } 
82     return 0;  
83 }
View Code

 

以上是关于Loj 6279. 数列分块入门 3的主要内容,如果未能解决你的问题,请参考以下文章

Loj 6279. 数列分块入门 3

LibreOj 6279数列分块入门 3 练习了一下set

#6279. 数列分块入门 3(询问区间内小于某个值 xx 的前驱(比其小的最大元素))

数列分块入门 3 题解

数列分块入门 3 题解

loj#6281. 数列分块入门 5