zoukankan      html  css  js  c++  java
  • 分块+二分 BZOJ 3343

    3343: 教主的魔法

    Time Limit: 10 Sec  Memory Limit: 256 MB
    Submit: 1312  Solved: 585
    [Submit][Status][Discuss]

    Description

    教主最近学会了一种神奇的魔法,能够使人长高。于是他准备演示给XMYZ信息组每个英雄看。于是N个英雄们又一次聚集在了一起,这次他们排成了一列,被编号为1、2、……、N
    每个人的身高一开始都是不超过1000的正整数。教主的魔法每次可以把闭区间[LR](1≤LRN)内的英雄的身高全部加上一个整数W。(虽然L=R时并不符合区间的书写规范,但我们可以认为是单独增加第LR)个英雄的身高)
    CYZ、光哥和ZJQ等人不信教主的邪,于是他们有时候会问WD闭区间 [LR] 内有多少英雄身高大于等于C,以验证教主的魔法是否真的有效。
    WD巨懒,于是他把这个回答的任务交给了你。
     

    Input

           第1行为两个整数NQQ为问题数与教主的施法数总和。
           第2行有N个正整数,第i个数代表第i个英雄的身高。
           第3到第Q+2行每行有一个操作:
    (1)       若第一个字母为“M”,则紧接着有三个数字LRW。表示对闭区间 [LR] 内所有英雄的身高加上W
    (2)       若第一个字母为“A”,则紧接着有三个数字LRC。询问闭区间 [LR] 内有多少英雄的身高大于等于C
     

    Output

           对每个“A”询问输出一行,仅含一个整数,表示闭区间 [LR] 内身高大于等于C的英雄数。
     

    Sample Input

    5 3
    1 2 3 4 5
    A 1 5 4
    M 3 5 1
    A 1 5 4

    Sample Output

    2
    3

    HINT

    【输入输出样例说明】

    原先5个英雄身高为1、2、3、4、5,此时[1, 5]间有2个英雄的身高大于等于4。教主施法后变为1、2、4、5、6,此时[1, 5]间有3个英雄的身高大于等于4。

     

    【数据范围】

    对30%的数据,N≤1000,Q≤1000。

    对100%的数据,N≤1000000,Q≤3000,1≤W≤1000,1≤C≤1,000,000,000。

    Source

     
    [Submit][Status][Discuss]

    思路:

    分块以后,对于每个询问区间[L,R],对于收尾两个区间进行暴力寻找即可。对于中间的块,我们提前进行排序然后进行二分寻找大于c-add[now_block_id]即可(因为每个块是sqrt(n)个元素,所以总的复杂度应该是n*sqrt(n)*log(n))

    //看看会不会爆int!数组会不会少了一维!
    //取物问题一定要小心先手胜利的条件
    #include <bits/stdc++.h>
    using namespace std;
    #pragma comment(linker,"/STACK:102400000,102400000")
    #define LL long long
    #define ALL(a) a.begin(), a.end()
    #define pb push_back
    #define mk make_pair
    #define fi first
    #define se second
    #define haha printf("haha
    ")
    const int maxn = 1000000 + 5;
    int n, q;
    int block, num, belong[maxn], L[maxn], R[maxn];
    int add[maxn], a[maxn], d[maxn];
    
    void build_block(){
        block = sqrt(n * 1.0); 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++){
            sort(d + L[i], d + R[i] + 1);
        }
    }
    
    void modify(int l, int r){
        for (int i = l; i <= r; i++)
            d[i] = a[i];
        sort(d + l, d + r + 1);
    }
    
    void update(int ql, int qr, int w){
        if (belong[ql] == belong[qr]){
            for (int i = ql; i <= qr; i++)
                a[i] += w;
            modify(L[belong[ql]], R[belong[ql]]);
            return ;
        }
        for (int i = ql; i <= R[belong[ql]]; i++)
            a[i] += w;
        modify(L[belong[ql]], R[belong[ql]]);
    
        for (int i = L[belong[qr]]; i <= qr; i++)
            a[i] += w;
        modify(L[belong[qr]], R[belong[qr]]);
    
        for (int i = belong[ql] + 1; i < belong[qr]; i++)
            add[i] += w;
    }
    
    int query(int ql, int qr, int c){
        int ans = 0;
        if (belong[ql] == belong[qr]){
            for (int i = ql; i <= qr; i++)
                if (c - add[belong[ql]] <= a[i]) ans++;
            return ans;
        }
        for (int i = ql; i <= R[belong[ql]]; i++)
            if (c - add[belong[ql]] <= a[i]) ans++;
    
        for (int i = L[belong[qr]]; i <= qr; i++)
            if (c - add[belong[qr]] <= a[i]) ans++;
        for (int i = belong[ql] + 1; i < belong[qr]; i++){
            int l = L[i], r = R[i];
            int p = lower_bound(d + l, d + r + 1, c - add[i]) - d;
            ans += r + 1 - p;
        }
        return ans;
    }
    
    int main(){
        cin >> n >> q;
        for (int i = 1; i <= n; i++){
            scanf("%d", a + i);
            d[i] = a[i];
        }
        build_block();
        while (q--){
            char ch[2]; int a, b, c;
            scanf("%s%d%d%d", ch, &a, &b, &c);
            if (ch[0] == 'A'){
                printf("%d
    ", query(a, b, c));
            }
            else update(a, b, c);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    LeetCode 1275. 找出井字棋的获胜者 Find Winner on a Tic Tac Toe Game
    LeetCode 307. 区域和检索
    LeetCode 1271 十六进制魔术数字 Hexspeak
    秋实大哥与花 线段树模板
    AcWing 835. Trie字符串统计
    Leetcode 216. 组合总和 III
    Mybatis 示例之 复杂(complex)属性(property)
    Mybatis 示例之 复杂(complex)属性(property)
    Mybatis 高级结果映射 ResultMap Association Collection
    Mybatis 高级结果映射 ResultMap Association Collection
  • 原文地址:https://www.cnblogs.com/heimao5027/p/6501540.html
Copyright © 2011-2022 走看看