P2801 教主的魔法

题目描述

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

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

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

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

输入输出格式

输入格式:

第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。

输出格式:

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

数据范围

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

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


考虑使用分块维护

发现没有添加或者删除,我们可以不写分裂合并

我们可以维护\(D\)个块,每个块大小为\(S\)

我们保证每个块都是有序的,这样

在查询的时候,边角直接暴力,整块二分即可

在修改的时候,边角直接暴力,整块打标记

发现单次操作的复杂度大概是\(O(DlogS+S)\)的

我们可以把块放的稍稍比\(\sqrt N\)大一点之类的


Code:

#include <cstdio>
#include <algorithm>
#include <cmath>
const int S=1e3+10;
const int N=1e6+10;
struct node
{
int pos,dat;
bool friend operator <(node n1,node n2)
{
return n1.dat<n2.dat;
}
}t[N];
int belong[N],L[S],R[S],lazy[S],delta[S],n,m,si,s;
void init()
{
scanf("%d%d",&n,&m);
s=sqrt(n);
for(int i=1;i<=n;i++)
scanf("%d",&t[i].dat);
for(si=1;si*s<=n;si++)
{
L[si]=(si-1)*s+1,R[si]=si*s;
for(int j=L[si];j<=R[si];j++)
belong[j]=si,t[j].pos=j;
}
if(R[si]<n)
{
L[si]=R[si-1]+1,R[si]=n;
for(int j=L[si];j<=R[si];j++)
belong[j]=si,t[j].pos=j;
}
L[si+1]=R[si]+1;
for(int i=1;i<=si;i++)
std::sort(t+L[i],t+R[i]+1);
}
void change(int l,int r,int w)
{
if(belong[l]==belong[r])
{
int now=belong[l];
for(int i=L[now];i<=R[now];i++)
if(t[i].pos<=r&&t[i].pos>=l)
t[i].dat+=w;
std::sort(t+L[now],t+R[now]+1);
}
else
{
for(int i=belong[l]+1;i<belong[r];i++)
delta[i]+=w;
int now=belong[l];
for(int i=L[now];i<=R[now];i++)
if(t[i].pos>=l)
t[i].dat+=w;
std::sort(t+L[now],t+R[now]+1);
now=belong[r];
for(int i=L[now];i<=R[now];i++)
if(t[i].pos<=r)
t[i].dat+=w;
std::sort(t+L[now],t+R[now]+1);
}
}
int query(int l,int r,int w)
{
int sum=0;
if(belong[l]==belong[r])
{
int now=belong[l];
for(int i=L[now];i<=R[now];i++)
if(t[i].pos>=l&&t[i].pos<=r&&t[i].dat+delta[now]>=w)
++sum;
}
else
{
for(int i=belong[l]+1;i<belong[r];i++)
{
int ll=L[i]-1,rr=R[i],tmp=t[ll].dat;
t[ll].dat=0;
while(ll<rr)
{
int mid=ll+rr+1>>1;
if(t[mid].dat+delta[i]<w)
ll=mid;
else
rr=mid-1;
}
sum+=R[i]-ll;t[L[i]-1].dat=tmp;
}
int now=belong[l];
for(int i=L[now];i<=R[now];i++)
if(t[i].pos>=l&&t[i].dat+delta[now]>=w)
++sum;
now=belong[r];
for(int i=L[now];i<=R[now];i++)
if(t[i].pos<=r&&t[i].dat+delta[now]>=w)
++sum;
}
return sum;
}
void work()
{
char c[3];
for(int l,r,w,i=1;i<=m;i++)
{
scanf("\n%c%d%d%d",c,&l,&r,&w);
if(c[0]=='M') change(l,r,w);
else printf("%d\n",query(l,r,w));
}
}
int main()
{
init();
work();
return 0;
}

2018.8.25

洛谷 P2801 教主的魔法 解题报告的更多相关文章

  1. 洛谷——P2801 教主的魔法(线段树or分块)

    P2801 教主的魔法 (1) 若第一个字母为“M”,则紧接着有三个数字L.R.W.表示对闭区间 [L, R] 内所有英雄的身高加上W. (2) 若第一个字母为“A”,则紧接着有三个数字L.R.C.询 ...

  2. 洛谷P2801 教主的魔法 [分块,二分答案]

    题目传送门 教主的魔法 题目描述 教主最近学会了一种神奇的魔法,能够使人长高.于是他准备演示给XMYZ信息组每个英雄看.于是N个英雄们又一次聚集在了一起,这次他们排成了一列,被编号为1.2.…….N. ...

  3. 洛谷P2801 教主的魔法 分块

    正解:分块 解题报告: 哇之前的坑还没填完就又写新博客? 不管不管,之前欠的两三篇题解大概圣诞节之前会再仔细想想然后重新写下题解趴,确实还挺难的感觉没有很好的理解呢QAQ还是太囫囵吞枣不求甚解了,这样 ...

  4. 洛谷 P2801 教主的魔法

    题目描述 教主最近学会了一种神奇的魔法,能够使人长高.于是他准备演示给XMYZ信息组每个英雄看.于是N个英雄们又一次聚集在了一起,这次他们排成了一列,被编号为1.2.…….N. 每个人的身高一开始都是 ...

  5. BZOJ——3343: 教主的魔法 || 洛谷—— P2801 教主的魔法

    http://www.lydsy.com/JudgeOnline/problem.php?id=3343  ||  https://www.luogu.org/problem/show?pid=280 ...

  6. 洛谷 P2797 Facer的魔法 解题报告

    P2797 Facer的魔法 题意:给你n个数,你可以选若干个数,使得平均数减中位数最大 数据范围:\(n \le 10^5\) 原题CF626E 很容易想到枚举一个中位数,但是如果选取的数字的个数是 ...

  7. [洛谷P2801]教主的魔法

    题目大意:有$n$个数,$q$个操作.两种操作: $M\;l\;r\;w:$把$[l,r]$所有数加上$w$ $A\;l\;r\;c:$查询$[l,r]$内大于等于$c$的元素的个数. 题解:分块,对 ...

  8. 洛谷 P2801 教主的魔法 题解

    题面 刚看到这道题的时候用了个树状数组优化前缀和差分的常数优化竟然AC了?(这数据也太水了吧~) 本人做的第一道分块题,调试了好久好久,最后竟然没想到二分上还会出错!(一定要注意)仅此纪念: #inc ...

  9. 洛谷_Cx的故事_解题报告_第四题70

    1.并查集求最小生成树 Code: #include <stdio.h> #include <stdlib.h>   struct node {     long x,y,c; ...

随机推荐

  1. sublime3常用插件总结

    本人之前使用的是webstorm,后来改用sublime,渐渐的爱上了它的快!(自行体会) 正式介绍sublime3常用的一些插件,安装流程不再赘述! SublimeTmpl 创建常用文件初始模板,必 ...

  2. Java : java基础(1)

    java编译器有常亮优化机制,如果是常量的计算,会直接判断常量计算结果的取值范围,如果是变量,则没办法判断计算取值范围,编译会异常(如两个byte类型的变量相加). java中的常量指的是用 stat ...

  3. 【PHP】array_column函数

    array_column() 返回输入数组中某个单一列的值. 例子,从记录集中取出 last_name 列: <?php // 表示由数据库返回的可能记录集的数组 $a = array( arr ...

  4. jquer搜索

    <body> <br/> <center> <tr><td>创建时间:</td><td><input type ...

  5. python_day4_shopping

    购物车例子,实现显示商品信息,输入商品编号并且可以减去自己的存入余额,当商品价格大于自己的余额的时候,直接退出:当不再选择商品的时候,退出显示余额和已经添加的商品. #购物车程序 product_li ...

  6. jmeter 插件安装

    1.下载Plugins Manager插件 打开下载插件地址:https://jmeter-plugins.org/ 2.将下载的plugins-manager.jar包复制到Jmeter安装目录,l ...

  7. HBase import tsv,csv File

    一,HBase中创建table 表(liupeng:test)并创建 info ,contect 列簇 hbase(main):258:0> create "liupeng:Test& ...

  8. 【jQuery】 Ajax

    [jQuery] Ajax $.ajax({ type: "Post", // 发包方式 cache: false, // 是否缓存 contentType: "appl ...

  9. 用起来超爽的Maven——入门篇

    你还在为怎样寻找.导入SSH相关依赖包纠结吗? 你还在为没有安装IDE开发工具不能编译.部署.运行项目而纠结吗? 你还在为公司项目目录结构怎样规范而纠结吗? 亲爱的纠结哥,只要你使用了Maven,一切 ...

  10. Scala学习笔记(四):从文件里读取文本行

    第一个版本: import scala.io.Source if(args.length>0){ for(line<-Source.fromFile(args(0)).getLines) ...