zoukankan      html  css  js  c++  java
  • [Luogu] 教主的魔法

    https://www.luogu.org/problemnew/show/P2801

    分块

    对于每一块进行排序存储在另一个数组中

    二分查询

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    
    using namespace std;
    
    #define gc getchar()
    
    const int N = 1e6 + 10;
    const int M = 1e3 + 10;
    
    int A[N], B[N], Pos[N], Add[M];
    int n, Q, cnt, block;
    
    inline int read(){
        int x = 0, f = 1; char c = gc;
        while(c < '0' || c > '9') {if(c == '-') f = -1; c = gc;}
        while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = gc;
        return x * f;
    }
    
    inline void Sort(int x){
        int l = (x - 1) * block + 1, r = min(n, x * block);
        for(int i = l; i <= r; i ++) B[i] = A[i];
        sort(B + l, B + r + 1);
    } 
    
    inline void Sec_G(int x, int y, int z){
        if(Pos[x] == Pos[y]){for(int i = x; i <= y; i ++) A[i] += z; Sort(Pos[x]); return ;}
        else {
            for(int i = x; i <= Pos[x] * block; i ++) A[i] += z;
            for(int i = (Pos[y] - 1) * block + 1; i <= y; i ++) A[i] += z;
            Sort(Pos[x]); Sort(Pos[y]);
        }
        for(int i = Pos[x] + 1; i < Pos[y]; i ++) Add[i] += z;
    }
    
    inline int to_calc(int x, int num){
        int l = (x - 1) * block, r = min(x * block, n), last = r, ans;
        while(l <= r){
            int mid = (l + r) >> 1;
            if(B[mid] < num) ans = mid, l = mid + 1;
            else r = mid - 1;
        }
        return last - ans + 1;
    }
    
    inline int Sec_A(int x, int y, int z){
        int answer(0);
        if(Pos[x] == Pos[y]){for(int i = x; i <= y; i ++) if(A[i] + Add[Pos[x]] >= z) answer ++; return answer;}
        else {
            for(int i = x; i <= Pos[x] * block; i ++) if(A[i] + Add[Pos[x]] >= z) answer ++;
            for(int i = (Pos[y] - 1) * block + 1; i <= y; i ++) if(A[i] + Add[Pos[y]] >= z) answer ++;
        }
        for(int i = Pos[x] + 1; i < Pos[y]; i ++) answer += to_calc(i, z - Add[i]);
        return answer;
    } 
    
    int main()
    {
        freopen("gg.in", "r", stdin);
        n = read(); Q = read();
        block = sqrt(n);
        for(int i = 1; i <= n; i ++) A[i] = read();
        for(int i = 1; i <= n; i ++) Pos[i] = (i - 1) / block + 1;
        for(int i = 1; i <= n; i ++) Sort(i);
        if(n % block) cnt = n / block + 1;
        else cnt = n / block;
        while(Q --){
            string s; cin >> s;
            int x = read(), y = read(), z = read();
            if(s[0] == 'A') Sec_G(x, y, z);
            else cout << Sec_A(x, y, z) << endl;
        }
        
        return 0;
    }
    /*
    5 3
    1 2 3 4 5
    A 1 5 4
    M 3 5 1
    A 1 5 4
    */
  • 相关阅读:
    C++中的explicitkeyword
    SQLite数据库查看工具(免费)
    C Tricks(十九)—— 求以任意数为底的对数
    分治法(divide & conquer)与动态规划(dynamic programming)应用举例
    分治法(divide & conquer)与动态规划(dynamic programming)应用举例
    C++组合数(combination)的实现
    C++组合数(combination)的实现
    算法求解方法与思路的总结
    算法求解方法与思路的总结
    使用 STL 辅助解决算法问题
  • 原文地址:https://www.cnblogs.com/shandongs1/p/8120184.html
Copyright © 2011-2022 走看看