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

    题目描述 Description###

    教主最近学会了一种神奇的魔法,能够使人长高。于是他准备演示给(XMYZ) 信息组每个英雄看。于是(N) 个英雄们又一次聚集在了一起,这次他们排成了一列,被编号为(1、2、……、N)

    每个人的身高一开始都是不超过1000的正整数。教主的魔法每次可以把闭区间$ [L, R]$ ((1≤L≤R≤N)) 内的英雄的身高全部加上一个整数W。(虽然(L=R) 时并不符合区间的书写规范,但我们可以认为是单独增加第(L)(R) )个英雄的身高)

    (CYZ) 、光哥和(ZJQ) 等人不信教主的邪,于是他们有时候会问(WD) 闭区间 ([L, R]) 内有多少英雄身高大于等于(C) ,以验证教主的魔法是否真的有效。

    (WD) 巨懒,于是他把这个回答的任务交给了你。

    输入描述 Input Description###

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

    输出描述 Output Description###

    对每个“(A) ”询问输出一行,仅含一个整数,表示闭区间 ([L, R]) 内身高大于等于(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
    

    数据范围及提示 Data Size & Hint###

    【输入输出样例说明】
    原先5个英雄身高为1、2、3、4、5,此时[1, 5]间有2个英雄的身高大于等于4。教主施法后变为1、2、4、5、6,此时[1, 5]间有3个英雄的身高大于等于4。
    【数据范围】
    对30%的数据,(N≤10^3)(Q≤10^3)
    对100%的数据,(N≤10^6)(Q≤3000)(1≤W≤10^3)(1≤C≤10^9)

    之前的一些废话###

    明天周六 开心,今晚终于能睡一个好觉了!

    题解###

    分块,新开一个数组块内排序,修改时暴力修改两端的,并且块内排序,对于中间的块直接打标记。查询时暴力查询两端,勿忘加上标记,对于中间的块在新数组中二分出对应位置即可。

    代码###

    #include<iostream>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #include<cstring>
    #include<cstdio>
    using namespace std;
    typedef long long LL;
    #define mem(a,b) memset(a,b,sizeof(a))
    typedef pair<int,int> PII;
    inline 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;
    }
    const int maxn=1000010;
    int n,q,size,A[maxn],id[maxn],tag[maxn],L[maxn],R[maxn],all,B[maxn],ql,qr,w;
    char tp[4];
    void bsort(int k)
    {
    	for(int i=L[k];i<=R[k];i++)A[i]+=tag[k],B[i]=A[i];
    	tag[k]=0;
    	sort(B+L[k],B+R[k]+1);
    }
    void update(int l,int r,int w)
    {
    	for(int i=l;i<=R[id[l]];i++)A[i]+=w;
    	bsort(id[l]);
    	if(id[l]!=id[r])
    	{
    		for(int i=L[id[r]];i<=r;i++)A[i]+=w;
    		bsort(id[r]);
    	}
    	for(int i=id[l]+1;i<=id[r]-1;i++)tag[i]+=w;
    }
    int query(int l,int r,int w)
    {
    	int x=id[l],y=id[r],cnt=0;
    	if(x==y){for(int i=l;i<=r;i++)cnt+=(A[i]+tag[x]>=w);return cnt;}
    	cnt=0;
    	for(int i=l;i<=R[x];i++)cnt+=(A[i]+tag[x]>=w);
    	for(int i=L[y];i<=r;i++)cnt+=(A[i]+tag[y]>=w);
    	for(int i=x+1;i<=y-1;i++)
    		cnt+=(R[i]-(lower_bound(B+L[i],B+R[i]+1,w-tag[i])-B)+1);
    	return cnt; 
    }
    int main()
    {
    	n=read();q=read();size=(int)sqrt(n);
    	for(int i=1;i<=n;i++)A[i]=B[i]=read(),id[i]=(i-1)/size+1; 
    	for(int i=1;i<=n;i+=size)L[++all]=i,R[all]=min(n,i+size-1);
    	for(int i=1;i<=all;i++)bsort(i);
    	while(q--)
    	{
    		scanf("%s",tp);
    		ql=read();qr=read();w=read();
    		if(tp[0]=='M')update(ql,qr,w);
    		else printf("%d
    ",query(ql,qr,w));
    	} 
    	return 0;
    }
    
    

    总结###

    分块要写出自己的风格,以此为鉴。

  • 相关阅读:
    java里面的设计模式
    MHRD_Guide
    flutter 入门(Mac)
    K8S实战-构建Django项目-03-使用共享存储
    《Effective Java》笔记45-56:通用程序设计
    机器学习实验二-集成学习
    -scp Linux之间复制文件和目录
    吴裕雄--天生自然 人工智能机器学习项目:地图数据及细胞图片数据处理报告(续五)
    吴裕雄--天生自然 人工智能机器学习项目:地图数据及细胞图片数据处理报告(续四)
    吴裕雄--天生自然 人工智能机器学习项目:地图数据及细胞图片数据处理报告(续二)
  • 原文地址:https://www.cnblogs.com/FYH-SSGSS/p/7700444.html
Copyright © 2011-2022 走看看