1. 程式人生 > >Loj 6278 數列分塊入門 3

Loj 6278 數列分塊入門 3

https begin 數列 == res tor col oid class

鏈接:https://loj.ac/problem/6279

思路:

和上一道一樣的方法,每個塊排序,兩端的塊暴力找,中間的塊二分找到比他小的最大的數,最後取最大的符合條件的數。

實現代碼:

#include<bits/stdc++.h>
using namespace std;
const int M = 1e5+10;
vector<int>v[M];
int a[M],block,n,bl[M],tag[M];
void reset(int x){
    v[x].clear();
    for(int i = (x-1)*block+1;i <= min(x*block,n);i ++)
        v[x].push_back(a[i]);
    sort(v[x].begin(),v[x].end());
}
void update(int l,int r,int c){ for(int i = l;i <= min(bl[l]*block,n);i ++){ a[i] += c; } reset(bl[l]); if(bl[l] != bl[r]){ for(int i = (bl[r]-1)*block+1;i <= r;i ++) a[i] += c; reset(bl[r]); } for(int i = bl[l]+1;i <= bl[r] - 1
;i ++) tag[i] += c; } int query(int l,int r,int c){ int ans = -1; for(int i = l;i <= min(bl[l]*block,r);i ++) if(a[i]+tag[bl[l]] < c) ans = max(ans,a[i]+tag[bl[l]]); if(bl[l] != bl[r]){ for(int i = (bl[r]-1)*block+1;i <= r;i ++) if(a[i]+tag[bl[r]] < c) ans = max(ans,a[i]+tag[bl[r]]); }
for(int i = bl[l]+1;i <= bl[r]-1;i ++){ int x = c - tag[i]; int y = lower_bound(v[i].begin(),v[i].end(),x) - v[i].begin(); if(y>=1) ans = max(ans,v[i][y-1]+tag[i]); } return ans; } int main(){ ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); int f,l,r,c; cin>>n; block = sqrt(n); for(int i = 1;i <= n;i ++) cin>>a[i]; for(int i = 1;i <= n;i ++){ bl[i] = (i-1)/block+1; v[bl[i]].push_back(a[i]); } for(int i = 1;i <= bl[n];i ++) sort(v[i].begin(),v[i].end()); for(int i = 1;i <= n;i ++){ cin>>f>>l>>r>>c; if(f == 0) update(l,r,c); else cout<<query(l,r,c)<<endl; } return 0; }

Loj 6278 數列分塊入門 3