LOJ #6279. 数列分块入门 3

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

先在每个块内排序,然后残块暴力,整块lower_bound。

指针形式运用lower_bound一定要小心啊啊啊 (调了1h+)

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstdio>
 4 #include<vector>
 5 #include<cstring>
 6 #include<cmath>
 7 #define pb push_back
 8 #define lb lower_bound
 9 #define val(i) (v[i]+atag[bl[i]])
10 using namespace std;
11 
12 const int Maxn = 50005*2;
13 int v[Maxn],atag[Maxn],bl[Maxn];
14 int opt,l,r,c,n,blo;
15 vector<int> V[Maxn];
16 
17 void reset(int x){
18     for(int i = (x-1)*blo+1;i <= min(n,x*blo);i++)
19         V[x][(i-1)%blo] = v[i];
20     sort(V[x].begin(),V[x].end());
21 }
22 
23 void change(int l,int r,int c){
24     if(l > r)return;
25     if(bl[l] == bl[r]){
26         for(int i = l;i <= r;i++)v[i] += c;
27         reset(bl[l]); return;
28     }
29     for(int i = l;i <= bl[l]*blo;i++)v[i] += c;reset(bl[l]);
30     for(int i = (bl[r]-1)*blo+1;i <= r;i++)v[i] += c;reset(bl[r]);
31     for(int i = bl[l]+1;i < bl[r];i++)atag[i] += c;
32 }
33 
34 int query(int l,int r,int c){
35     if(l > r)return -1;
36     int ans = -1;
37     if(bl[l] == bl[r]){
38         for(int i = l;i <= r;i++)
39             if(ans < val(i)&&val(i) < c)ans = val(i);
40         return ans;
41     }
42     for(int i = l;i <= bl[l]*blo;i++)
43         if(ans < val(i)&&val(i) < c)ans = val(i);//
44     for(int i = (bl[r]-1)*blo+1;i <= r;i++)
45         if(ans < val(i)&&val(i) < c)ans = val(i);//
46     for(int i = bl[l]+1;i < bl[r];i++){
47         vector<int>::iterator x = lb(V[i].begin(),V[i].end(),c-atag[i]);
48         if(x == V[i].begin())continue;x--;
49         while(x != V[i].begin()&&*x >= c-atag[i])x--;
50         if(ans-atag[i] < *x&&*x < c-atag[i])ans = *x+atag[i];
51     }
52     return ans;
53 }
54 
55 int main(){
56     scanf("%d",&n);blo = sqrt(n);
57     for(int i = 1;i <= n;i++){
58         scanf("%d",&v[i]);
59         bl[i] = (i-1)/blo+1;
60         V[bl[i]].pb(v[i]);
61     }
62     for(int i = 1;i <= bl[n];i++)
63         sort(V[i].begin(),V[i].end());
64     for(int i = 1;i <= n;i++){
65         scanf("%d%d%d%d",&opt,&l,&r,&c);
66         if(opt == 1)printf("%d\n",query(l,r,c));
67         if(opt == 0)change(l,r,c);
68     }    
69 return 0;
70 }

 

posted @ 2019-11-02 10:56  TIH_HIT  阅读(179)  评论(0编辑  收藏  举报