码迷,mamicode.com
首页 > 其他好文 > 详细

[Luogu] 教主的魔法

时间:2017-12-26 22:44:27      阅读:141      评论:0      收藏:0      [点我收藏+]

标签:lin   define   ios   ast   add   二分   ++   get   lock   

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
*/

 

[Luogu] 教主的魔法

标签:lin   define   ios   ast   add   二分   ++   get   lock   

原文地址:https://www.cnblogs.com/shandongs1/p/8120184.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!