zoukankan      html  css  js  c++  java
  • [LOJ] 分块九题 3

    https://loj.ac/problem/6279

    区间修改,区间查询前驱。

    TLE无数,我觉得这代码最精髓的就是block=1000。
    谜一样的1000。

    两个启示:

    1. 块内可以维护数据结构,比如set
    2. 可以换换块大小,自造数据测试时间
    //Stay foolish,stay hungry,stay young,stay simple
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<cstdio>
    #include<cctype>
    #include<set>
    #define R register
    using namespace std;
    
    
    const int nINF=-(1<<29);
    const int MAXN=500005;
    
    set<int> b[1000];
    
    void Out(int x)  
    {  
        if(x<0)  
        {  
            putchar('-');x=-x;  
        }  
        if(x>9)Out(x/10);  
        putchar(x%10+'0');  
    }  
    
    inline int read_d(){
        int ret=0,f=1;char c;
        while(c=getchar(),!isdigit(c)) f=c=='-'?-1:1;
        while(isdigit(c)){
            ret*=10;ret+=c-'0';
            c=getchar();
        }
        return f*ret;
    }
    
    int n;
    
    int a[MAXN],inc[MAXN],l[MAXN],
        r[MAXN],bl[MAXN];
    int block,num;
    
    void reset(int id){
        b[id].clear();
        for(R int i=l[id];i<=r[id];i++) b[id].insert(a[i]); 
    } 
    
    void build(){
    //    block=sqrt(n);
    //    block>>=1;
        block=1000;//玄学?!?!?!?!? 
        num=n/block;
        if(n%block) num++;
        for(int i=1;i<=n;i++){
            l[i]=(i-1)*block+1;
            r[i]=i*block;
        }
        r[num]=n;
        for(R int i=1;i<=n;i++)
            bl[i]=(i-1)/block+1;
        for(R int i=1;i<=n;i++) b[bl[i]].insert(a[i]); 
    }
    
    void updata(int x,int y,int w){
        if(bl[x]==bl[y]){
            for(int i=x;i<=y;i++)
                b[bl[i]].erase(a[i]),a[i]+=w,b[bl[i]].insert(a[i]); 
            return;
        }
        for(R int i=x;i<=r[bl[x]];i++){
            b[bl[i]].erase(a[i]);
            a[i]+=w;
            b[bl[i]].insert(a[i]);
        }
        for(R int i=bl[x]+1;i<=bl[y]-1;i++) 
            inc[i]+=w;
        for(R int i=l[bl[y]];i<=y;i++){
            b[bl[i]].erase(a[i]);
            a[i]+=w;
            b[bl[i]].insert(a[i]);
        }
    }
    
    int query(int x,int y,int w){
        int ret=nINF;
        if(bl[x]==bl[y]){
            ret=-1;
            for(int i=x;i<=y;i++){
                int v=a[i]+inc[bl[i]];
                if(v<w) ret=max(ret,v);
            }
            return ret;     
        }
        for(R int i=x;i<=r[bl[x]];i++){
            int v=a[i]+inc[bl[i]];
            if(v<w) ret=max(ret,v);
        }
        for(R int i=l[bl[y]];i<=y;i++){
            int v=a[i]+inc[bl[i]];
            if(v<w) ret=max(ret,v);
        } 
        for(R int i=bl[x]+1;i<=bl[y]-1;i++){
            set<int>::iterator it = b[i].lower_bound(w-inc[i]);
            if(it==b[i].begin())continue;
            --it;
            ret = max(ret,*it+inc[i]);
        }
        return ret;
    }
    
    int main(){
    //  freopen("in.txt","r",stdin);
    //  freopen("test.txt","w",stdout);
        n=read_d();
        for(R int i=1;i<=n;i++) a[i]=read_d();
        build();
        for(R int i=1;i<=n;i++){
            int q,x,y,z;
            q=read_d();
            x=read_d();
            y=read_d();
            z=read_d();
            if(q==0) updata(x,y,z);
            else {
                int ans=query(x,y,z);
                if(ans==nINF) puts("-1");
                else Out(ans),putchar('
    ');
            }
        }
        return 0;
    }

    本文来自博客园,作者:GhostCai,转载请注明原文链接:https://www.cnblogs.com/ghostcai/p/9247438.html

  • 相关阅读:
    __setattr__,__getattr__,__delattr__
    LeetCode 面试题42. 连续子数组的最大和
    LeetCode 53. 最大子序和
    LeetCode 面试题39. 数组中出现次数超过一半的数字
    LeetCode 169. 多数元素
    LeetCode 426.将二叉搜索树转化为排序的双向链表
    LeetCode 面试题36. 二叉搜索树与双向链表
    LeetCode 面试题35. 复杂链表的复制
    LeetCode 138. 复制带随机指针的链表
    LeetCode 面试题34. 二叉树中和为某一值的路径
  • 原文地址:https://www.cnblogs.com/ghostcai/p/9247438.html
Copyright © 2011-2022 走看看