• 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;
    }
  • 相关阅读:
    7天入门JavaScript,第一天
    linux 下 启动web项目报 java.net.UnknownHostException
    HashMap 和 Hashtable
    Servlet 两种跳转方式
    SpringMVC
    把当前时间(NSDate)转为字符串
    写入数据到Plist文件中时,第一次要创建一个空的数组,否则写入文件失败
    实现多个UIView之间切换的动画效果
    missing required architecture x86_64 in file 不支持64位
    获取IOS bundle中的文件
  • 原文地址:https://www.cnblogs.com/ckxkexing/p/8970329.html
Copyright © 2020-2023  润新知