BZOJ 3343 教主的魔法(分块)

题意:

有一个1e6的数组,t次操作:将[l,r]内的值增加w,或者查询[l,r]内的值大于等于add的

思路:

分块,块大小为sqrt(n),每次只需要暴力头尾两块,中间的整块打标记,

对于查询查操作,块内排序然后二分即可

复杂度O(T(sqrt(n)+sqrt(n)logn))

代码:

可以弄两个数组对应着写,会比我这样stl乱写快一倍

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<stack>
#include<queue>
#include<deque>
#include<set>
#include<vector>
#include<map>
 
#define fst first
#define sc second
#define pb push_back
#define mem(a,b) memset(a,b,sizeof(a))
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lc root<<1
#define rc root<<1|1
//#define lowbit(x) ((x)&(-x)) 
 
using namespace std;
 
typedef double db;
typedef long double ldb;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> PI;
typedef pair<ll,ll> PLL;
 
const db eps = 1e-6;
const int mod = 1e9+7;
const int maxn = 1e6+100;
const int maxm = 2e6+100;
const int inf = 0x3f3f3f3f;
 
//const db pi = acos(-1.0);
 

struct node{
    int id;
    ll v;
};
int n, q;
vector<node>blc[maxn];
int block;
bool cmp(node a, node b){
    return a.v<b.v;
}
ll add[maxn];
int main(){
    scanf("%d %d", &n, &q);
    int block = (int)sqrt(n);
    for(int i = 0; i < n; i++){
        node tmp;
        tmp.id = i;
        scanf("%lld", &tmp.v);
        blc[i/block].pb(tmp);
    }
    for(int i = 0; i <= (n-1)/block; i++){
        sort(blc[i].begin(), blc[i].end(), cmp);
    }
    while(q--){
        char op[3];
        int x, y;
        ll w;
        scanf("%s",op+1);
        scanf("%d %d %lld", &x, &y, &w);
        x--;y--;
        int bx = x/block;
        int by = y/block;
        if(op[1]=='M'){
            if(bx==by){
                for(int i = 0; i < (int)blc[bx].size(); i++){
                    node a = blc[bx][i];
                    if(a.id>=x&&a.id<=y)blc[bx][i].v+=w;
                }
                sort(blc[bx].begin(), blc[bx].end(),cmp);
            }
            else{
                int rx = min(n-1, (bx+1)*block-1);
                int ly = by*block;
                for(int i = 0; i < (int)blc[bx].size(); i++){
                    int id = blc[bx][i].id;
                    if(id>=x&&id<=y)blc[bx][i].v+=w;
                }sort(blc[bx].begin(), blc[bx].end(),cmp);
                for(int i = 0; i < (int)blc[by].size(); i++){
                    int id = blc[by][i].id;
                    if(id>=x&&id<=y)blc[by][i].v+=w;
                }sort(blc[by].begin(), blc[by].end(),cmp);
                for(int i = bx+1; i < by; i++){
                    add[i]+=w;
                }
            }
        }
        else{
            int ans = 0;
            if(bx==by){
                for(int i = 0; i < (int)blc[bx].size(); i++){
                    int id = blc[bx][i].id;
                    if(id>=x&&id<=y&&blc[bx][i].v+add[bx]>=w)ans++;
                }
            }
            else{
                for(int i = 0; i < (int)blc[bx].size(); i++){
                    int id = blc[bx][i].id;
                    if(id>=x&&id<=y&&blc[bx][i].v+add[bx]>=w)ans++;
                }
                for(int i = 0; i < (int)blc[by].size(); i++){
                    int id = blc[by][i].id;
                    if(id>=x&&id<=y&&blc[by][i].v+add[by]>=w)ans++;
                }
                //printf("--%d\n",ans);
                for(int i = bx+1; i < by; i++){
                    ll x = w-add[i];
                    int l = 0;
                    int r = block-1;
                    int pos = block;
                    while(l<=r){
                        int mid = (l+r)>>1;
                        if(blc[i][mid].v>=x){
                            pos = mid;
                            r = mid-1;
                        }
                        else l = mid+1;
                    }
                    ans+=block-pos;
                }
            }
            printf("%d\n",ans);
        }
    }
    return 0;
}
/*
5 3
1 2 3 4 5
A 1 5 4
M 3 5 1
A 1 5 4

5 7
3 1 4 2 5
A 1 5 4
M 3 5 1
M 3 5 2
A 1 5 4
M 1 1 3
A 1 5 4
A 1 5 10

5 3
3 1 4 2 5
A 1 5 10
M 1 5 2
A 1 5 10
 */

 

posted @ 2019-07-15 15:35  wrjlinkkkkkk  阅读(281)  评论(0编辑  收藏  举报