码迷,mamicode.com
首页 > 其他好文 > 详细

数列分块入门 3 题解

时间:2020-05-16 15:13:10      阅读:55      评论:0      收藏:0      [点我收藏+]

标签:pac   back   ++   eset   int   sqrt   tps   target   printf   

https://loj.ac/problem/6279

vector+块内二分。

修改时需要重构,查询时可以二分查出来。

不要忘记 add 标记!

#pragma GCC diagnostic error "-std=c++14"
#pragma GCC target("avx")
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
using namespace std;
int n,bl,m,opt,l,r,v;
int a[100010], pos[100010], add[100010],L[100010],R[100010];
vector<int> b[100010];
void reset(int x) {
    b[x].clear();
    for(int i=L[x]; i<=R[x]; i++)
        b[x].push_back(a[i]+=add[x]);
    sort(b[x].begin(),b[x].end());
    add[x]=0;
    return;
}//对第 x 块进行重构,并加上标记
void update(int l, int r, int v) {
    if(pos[l]==pos[r]) {
        for(int i=l; i<=r; i++)
            a[i]+=v;
        reset(pos[l]);
        return;
    }
    for(int i=l; i<=R[pos[l]]; i++)
        a[i]+=v;
    reset(pos[l]);
    for(int i=L[pos[r]]; i<=r; i++)
        a[i]+=v;
    reset(pos[r]);
    for(int i=pos[l]+1; i<=pos[r]-1; i++)
        add[i]+=v;
    return;
}
int query(int l, int r, int v) {
    int ans=-1;
    if(pos[l]==pos[r]) {
        for(int i=l; i<=r; i++)
            if(a[i]+add[pos[i]]<v)
                ans=max(ans,a[i]+add[pos[i]]);
        return ans;
    }
    for(int i=l;i<=R[pos[l]];i++)
        if(a[i]+add[pos[i]]<v)
            ans=max(ans,a[i]+add[pos[i]]);
    for(int i=L[pos[r]];i<=r;i++)
        if(a[i]+add[pos[i]]<v)
            ans=max(ans,a[i]+add[pos[i]]);
    for(int i=pos[l]+1;i<=pos[r]-1;i++) {
        int kk=lower_bound(b[i].begin(),b[i].end(),v-add[i])-b[i].begin();
        if(kk>0)
            ans=max(ans,b[i][kk-1]+add[i]);//二分查找
    }
    return ans;
}
int main() {
    scanf("%d", &n);
    bl = sqrt(n);
    for (int i = 1; i <= n; i++) {
        scanf("%d", &a[i]);
        pos[i] = (i - 1) /bl + 1;
        b[pos[i]].push_back(a[i]);
    }
    for(int i=1; i<=pos[n]; i++)
        L[i]=(i-1)*bl+1,R[i]=i*bl;
    R[pos[n]]=n;
    for(int i=1; i<=pos[n]; i++)
        sort(b[i].begin(),b[i].end());
    for (int i = 1; i <= n; i++) {
        int ch;
        int x, y, v;
        scanf("%d %d %d %d", &ch, &x, &y, &v);
        if (ch == 0)
            update(x, y, v);
        else
            printf("%d\n", query(x, y, v));
    }
    return 0;
}

数列分块入门 3 题解

标签:pac   back   ++   eset   int   sqrt   tps   target   printf   

原文地址:https://www.cnblogs.com/lajiccf/p/12900562.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!