• BZOJ-3343教主的魔法+分块(大块排序二分)


    传送门:https://www.luogu.org/problemnew/show/P2801

    参考:http://hzwer.com/2784.html  感觉思路无比清晰;)

    ps:我在洛谷A的,BZOJ要权限;

    题意:区间查询有多少个比K的数;

    思路:分块,两边暴力更新与查询,中间查询是用二分计数;每次更新,如有必要,要记得重新sort(区间对应的另一个数组);

    #include <iostream>
    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <string>
    using namespace std;
    typedef long long ll;
    const int maxn = 1000009;
    const int bmaxn = 1009;
    ll a[maxn],b[maxn],add[bmaxn];
    int n,m;
    
    int belong[maxn];       
    int num,l[bmaxn],r[bmaxn];        //块个数;i这块的左端;i这块的右端
    int block;                      //块大小
    
    void reset(int id)
    {
        int le = l[id],ri = r[id];
        for(int i=le; i<=ri; i++)b[i] = a[i];
        sort(b+le,b+ri+1);
    }
    
    void build()
    {
        block = sqrt(n);
        num = n/block;if(n%block)num++;
        for(int i=1; i<=num; i++)
            l[i]=(i-1)*block+1,r[i] = i * block;
        r[num] = n;
        for(int i=1; i<=n; i++)
            belong[i]  = (i-1)/block + 1;
        for(int i=1; i <= num; i++)
            reset(i);
    }
    
    void update(int lx,int rx,ll val)
    {
        if(belong[lx]==belong[rx])
        {
            for(int i=lx;i<=rx;i++)a[i]+=val;
            reset(belong[lx]);
        }
        else
        {
            int li = r[belong[lx]],ri = l[belong[rx]];
            for(int i = lx; i<=li; i++)a[i]+=val;
                reset(belong[lx]);
            for(int i = ri; i<=rx; i++)a[i]+=val;
                reset(belong[rx]);
            for(int i = belong[lx] + 1;i < belong[rx]; i++)add[i]+=val;
        }
    }
    
    ll query(int lx,int rx,ll k)
    {
        ll res = 0;
        if(belong[lx]==belong[rx])
        {
            for(int i=lx;i<=rx;i++)if(a[i] >= k - add[belong[lx]])res++;
        }
        else 
        {
            int li = r[belong[lx]],ri = l[belong[rx]];
            // cout<<li<<" "<<ri<<endl;
            for(int i = lx; i <= li; i++) if(a[i] >= k-add[belong[lx]])res++;
            for(int i = ri; i <= rx; i++) if(a[i] >= k-add[belong[rx]])res++;
            for(int i = belong[lx] + 1; i<belong[rx]; i++)
            {
                int le = l[i],ri = r[i];
                while(le <= ri)
                {
                    int mid = (le+ri)>>1;
                    if(b[mid] < k - add[i])
                        le = mid + 1;
                    else ri = mid - 1;
                }
                // printf("%d
    ",le);
                // cout<<r[i]-le+1<<endl;
                res+=r[i] - le + 1;
            }
        }
        return res;
    }
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1; i<=n; i++)
            scanf("%lld", &a[i]);
        build();
        for(int i=1; i<=m; i++)
        {
            char s[20];
            int x,y;
            ll v;
            scanf("%s%d%d%lld",s,&x,&y,&v);
            if(s[0]=='M')
            {
                update(x,y,v);
            }
            else
            {
                ll ans = query(x,y,v);
                printf("%lld
    ",ans);
            }
        }
        return 0;
    }
  • 相关阅读:
    莎士比亚名言
    庄子名言
    Javascript: 通过图片url获取图片blob对象
    toast提示 封装
    maya模型导入UE4,如何做到等比导入
    GPU渲染和CPU渲染农场成本对比
    C4D渲线框
    C4D教程笔记——高科技线框3D模型全息投影 X-Wing Hologram Animation
    arnold和redshift渲染器
    使用Redshift渲染器,怎么选电脑配置!
  • 原文地址:https://www.cnblogs.com/ckxkexing/p/8970329.html
Copyright © 2020-2023  润新知