zoukankan      html  css  js  c++  java
  • 【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


    题解

    分块+二分

    分成√n 个块,对于每个块另开一个数组将h[i]排序。

    修改时,整块直接打add标记,多余部分暴力改,然后重排序。

    查询时,整块使用排序后的数组二分查找大于等于c-add的个数,多余部分暴力查询。

    注意l和r同块时的特判。

    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    using namespace std;
    int n , si , h[1000010] , v[1000010] , add[1010];
    char str[5];
    void reset(int b)
    {
    	int i , l = b * si , r = min((b + 1) * si - 1 , n - 1);
    	for(i = l ; i <= r ; i ++ ) v[i] = h[i];
    	sort(v + l , v + r + 1);
    }
    int search(int b , int lim)
    {
    	int l = b * si , r = min((b + 1) * si - 1 , n - 1) , mid , ans = r + 1 , tr = r;
    	while(l <= r)
    	{
    		mid = (l + r) >> 1;
    		if(v[mid] + add[b] >= lim) ans = mid , r = mid - 1;
    		else l = mid + 1;
    	}
    	return tr - ans + 1;
    }
    int main()
    {
    	int	m , i , l , r , x , ans;
    	scanf("%d%d" , &n , &m);
    	si = (int)sqrt(n);
    	for(i = 0 ; i < n ; i ++ ) scanf("%d" , &h[i]);
    	for(i = 0 ; i * si < n ; i ++ ) reset(i);
    	while(m -- )
    	{
    		scanf("%s%d%d%d" , str , &l , &r , &x);
    		l -- , r -- ;
    		if(str[0] == 'M')
    		{
    			if(l / si == r / si)
    			{
    				for(i = l ; i <= r ; i ++ ) h[i] += x;
    				reset(l / si);
    			}
    			else
    			{
    				for(i = l / si + 1 ; i < r / si ; i ++ ) add[i] += x;
    				for(i = l ; i < (l / si + 1) * si ; i ++ ) h[i] += x;
    				for(i = r / si * si ; i <= r ; i ++ ) h[i] += x;
    				reset(l / si) , reset(r / si);
    			}
    		}
    		else
    		{
    			ans = 0;
    			if(l / si == r / si)
    				for(i = l ; i <= r ; i ++ )
    					ans += (h[i] + add[l / si] >= x);
    			else
    			{
    				for(i = l / si + 1 ; i < r / si ; i ++ ) ans += search(i , x);
    				for(i = l ; i < (l / si + 1) * si ; i ++ ) ans += (h[i] + add[l / si] >= x);
    				for(i = r / si * si ; i <= r ; i ++ ) ans += (h[i] + add[r / si] >= x);
    			}
    			printf("%d
    " , ans);
    		}
    	}
    	return 0;
    }

     

  • 相关阅读:
    常见jvm命令
    服务后台启动
    kafka创建topic,生产和消费指定topic消息
    kafka-manager安装
    修改ssh主机名
    设置虚拟机静态ip
    kafka术语
    cas和oauth2的区别
    会Python的大学生,步入职场将会非常抢手!
    python爬虫把url链接编码成gbk2312格式过程解析
  • 原文地址:https://www.cnblogs.com/GXZlegend/p/6591298.html
Copyright © 2011-2022 走看看