• [BZOJ3343]教主的魔法


    [BZOJ3343]教主的魔法

    试题描述

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

    输入

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

    输出

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

    输入示例

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

    输出示例

    2
    3

    数据规模及约定

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

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

    题解

    这题询问较少,但 N 比较大,可以往 O(Q√n) 复杂度的算法这个方向去想,况且这个题目用数据结构很难维护,所以就会想到分块。

    想到分块之后就很简单了,每个块内部排一遍序,整块查询时可以二分,边上两块就可以暴力处理了。

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <stack>
    #include <vector>
    #include <queue>
    #include <cstring>
    #include <string>
    #include <map>
    #include <set>
    using namespace std;
    
    const int BufferSize = 1 << 16;
    char buffer[BufferSize], *Head, *Tail;
    inline char Getchar() {
        if(Head == Tail) {
            int l = fread(buffer, 1, BufferSize, stdin);
            Tail = (Head = buffer) + l;
        }
        return *Head++;
    }
    int read() {
        int x = 0, f = 1; char c = Getchar();
        while(!isdigit(c)){ if(c == '-') f = -1; c = Getchar(); }
        while(isdigit(c)){ x = x * 10 + c - '0'; c = Getchar(); }
        return x * f;
    }
    
    #define maxn 1000010
    #define maxb 1010
    int n, q, A[maxn], Blo[maxn], st[maxb], en[maxb], addv[maxb], cb, pos[maxn];
    
    void update(int l, int r, int val) {
    	int bl = pos[l], br = pos[r];
    	if(br - bl < 2) {
    		for(int i = st[bl]; i <= en[br]; i++) A[i] += addv[pos[i]]; addv[bl] = addv[br] = 0;
    		for(int i = l; i <= r; i++) A[i] += val;
    		for(int i = st[bl]; i <= en[br]; i++) Blo[i] = A[i];
    		sort(Blo + st[bl], Blo + en[bl] + 1);
    		sort(Blo + st[br], Blo + en[br] + 1);
    		return ;
    	}
    	for(int i = st[bl]; i <= en[bl]; i++) A[i] += addv[bl]; addv[bl] = 0;
    	for(int i = st[br]; i <= en[br]; i++) A[i] += addv[br]; addv[br] = 0;
    	for(int i = l; i <= en[bl]; i++) A[i] += val;
    	for(int i = st[br]; i <= r; i++) A[i] += val;
    	for(int i = st[bl]; i <= en[bl]; i++) Blo[i] = A[i]; sort(Blo + st[bl], Blo + en[bl] + 1);
    	for(int i = st[br]; i <= en[br]; i++) Blo[i] = A[i]; sort(Blo + st[br], Blo + en[br] + 1);
    	for(int i = bl + 1; i <= br - 1; i++) addv[i] += val;
    	return ;
    }
    int query(int l, int r, int val) {
    	int bl = pos[l], br = pos[r], ans = 0;
    	if(br - bl < 2) {
    		for(int i = st[bl]; i <= en[br]; i++) A[i] += addv[pos[i]], Blo[i] += addv[pos[i]];
    		addv[bl] = addv[br] = 0;
    		for(int i = l; i <= r; i++) ans += (A[i] >= val);
    		return ans;
    	}
    	for(int i = st[bl]; i <= en[bl]; i++) A[i] += addv[bl], Blo[i] += addv[bl]; addv[bl] = 0;
    	for(int i = st[br]; i <= en[br]; i++) A[i] += addv[br], Blo[i] += addv[br]; addv[br] = 0;
    	for(int i = l; i <= en[bl]; i++) ans += (A[i] >= val);
    	for(int i = st[br]; i <= r; i++) ans += (A[i] >= val);
    	for(int i = bl + 1; i <= br - 1; i++) {
    		int x = lower_bound(Blo + st[i], Blo + en[i] + 1, val - addv[i]) - Blo;
    		if(Blo[x] >= val - addv[i]) x--;
    		if(en[i] > x) ans += en[i] - x;
    	}
    	return ans;
    }
    
    int main() {
    	n = read(); q = read();
    	int t = (int)(sqrt(n) + .5);
    	for(int i = 1; i <= n; i++) {
    		A[i] = Blo[i] = read();
    		int ni = (i - 1) / t + 1; cb = ni;
    		if(!st[ni]) st[ni] = i; en[ni] = i;
    		pos[i] = ni;
    	}
    	
    	for(int i = 1; i <= cb; i++) sort(Blo + st[i], Blo + en[i] + 1);
    	while(q--) {
    		char tp = Getchar();
    		while(!isalpha(tp)) tp = Getchar();
    		int ql = read(), qr = read(), val = read();
    		if(tp == 'M') update(ql, qr, val);
    		if(tp == 'A') printf("%d
    ", query(ql, qr, val));
    	}
    	
    	return 0;
    }
    

    教主的这个魔法能不能在我身上用一下啊 QAQ

  • 相关阅读:
    深入理解JavaScript系列
    Knockout应用开发指南(完整版) 目录索引
    js原生设计模式——8单例模式之简约版属性样式方法库
    彻底理解JavaScript原型
    Javascript模块化编程(一):模块的写法
    使用Grunt构建自动化开发环境
    js原生之一个面向对象的应用
    js原生之函数
    angular源码分析:angular中的依赖注入式如何实现的
    js原生之scrollTop、offsetHeight和offsetTop等属性用法详解
  • 原文地址:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/5744499.html
Copyright © 2020-2023  润新知