zoukankan      html  css  js  c++  java
  • 数列分块入门 3 题解

    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
    ", query(x, y, v));
        }
        return 0;
    }
    
    少说话,多做事。 ——cnyz 留
  • 相关阅读:
    SSH免密码登录
    Qt编译错误GL/gl.h: No such file or directory
    UVA 11645
    《逆袭大学》文摘——9.4 基础和应用的平衡中找到大学的节奏
    EBS採购模块中的高速接收和高速接收事务
    笔记-Android中打开各种格式的文件(apk、word、excel、ppt、pdf、音视频、图片等)
    git 冲突解决的方法
    SICP 习题 (1.43)解题总结
    Swift百万线程攻破单例(Singleton)模式
    setjmp/longjmp
  • 原文地址:https://www.cnblogs.com/lajiccf/p/12900562.html
Copyright © 2011-2022 走看看