洛谷 P2801 教主的魔法 解题报告
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 教主的魔法 解题报告的更多相关文章
- 洛谷——P2801 教主的魔法(线段树or分块)
P2801 教主的魔法 (1) 若第一个字母为“M”,则紧接着有三个数字L.R.W.表示对闭区间 [L, R] 内所有英雄的身高加上W. (2) 若第一个字母为“A”,则紧接着有三个数字L.R.C.询 ...
- 洛谷P2801 教主的魔法 [分块,二分答案]
题目传送门 教主的魔法 题目描述 教主最近学会了一种神奇的魔法,能够使人长高.于是他准备演示给XMYZ信息组每个英雄看.于是N个英雄们又一次聚集在了一起,这次他们排成了一列,被编号为1.2.…….N. ...
- 洛谷P2801 教主的魔法 分块
正解:分块 解题报告: 哇之前的坑还没填完就又写新博客? 不管不管,之前欠的两三篇题解大概圣诞节之前会再仔细想想然后重新写下题解趴,确实还挺难的感觉没有很好的理解呢QAQ还是太囫囵吞枣不求甚解了,这样 ...
- 洛谷 P2801 教主的魔法
题目描述 教主最近学会了一种神奇的魔法,能够使人长高.于是他准备演示给XMYZ信息组每个英雄看.于是N个英雄们又一次聚集在了一起,这次他们排成了一列,被编号为1.2.…….N. 每个人的身高一开始都是 ...
- BZOJ——3343: 教主的魔法 || 洛谷—— P2801 教主的魔法
http://www.lydsy.com/JudgeOnline/problem.php?id=3343 || https://www.luogu.org/problem/show?pid=280 ...
- 洛谷 P2797 Facer的魔法 解题报告
P2797 Facer的魔法 题意:给你n个数,你可以选若干个数,使得平均数减中位数最大 数据范围:\(n \le 10^5\) 原题CF626E 很容易想到枚举一个中位数,但是如果选取的数字的个数是 ...
- [洛谷P2801]教主的魔法
题目大意:有$n$个数,$q$个操作.两种操作: $M\;l\;r\;w:$把$[l,r]$所有数加上$w$ $A\;l\;r\;c:$查询$[l,r]$内大于等于$c$的元素的个数. 题解:分块,对 ...
- 洛谷 P2801 教主的魔法 题解
题面 刚看到这道题的时候用了个树状数组优化前缀和差分的常数优化竟然AC了?(这数据也太水了吧~) 本人做的第一道分块题,调试了好久好久,最后竟然没想到二分上还会出错!(一定要注意)仅此纪念: #inc ...
- 洛谷_Cx的故事_解题报告_第四题70
1.并查集求最小生成树 Code: #include <stdio.h> #include <stdlib.h> struct node { long x,y,c; ...
随机推荐
- JZOJ 5943. 树
Description
- elasticsearch 5.x 系列之四(索引模板的使用,详细得不要不要的)
1,首先看一下下面这个索引模板 curl -XPUT "master:9200/_template/template_1?pretty" -H 'Content-Type: app ...
- 003---socket介绍
socket介绍 什么是socket? socket是应用层与tcp/ip协议族通信的中间软件抽象层,它是一组接口.在设计模式中.其实就是一个门面模式.我们无需深入理解tcp/udp协议,socket ...
- R语言绘图:雷达图
使用fmsb包绘制雷达图 library("fmsb") radarfig <- rbind(rep(90, 4), rep(60, 4), c(86.17, 73.96, ...
- win10 无法修改默认程序 默认打开方式的解决方法
此时是2018年11月24日 win10 pro 64位 版本是1803 具体版本号是17134 情景: 我的状况是.json文件的默认打开方式被新安装的应用霸占了,然后无论是通过“右键-属性-更改 ...
- spring、spring-data-redis整合使用
一.Redis是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,并提供多种语言的API. 从2010年3月15日起,Redis的开发工作由VMwa ...
- Linux使用imagemagick的convert命令压缩图片,节省服务器空间
1,安装imagemagick yum install ImageMagick 2,获取图片 find ./ -regex '.*\(jpg\|JPG\|png\|jpeg\)' -size +500 ...
- Java测试工具和框架
个人目前只接触过JUnit以及Powermock,后续会关注更多有关测试这方面的东西 8个超实用的Java测试工具和框架_开发/数据库_IT专家网 http://database.ctocio.com ...
- xshell、xftp免费版下载方法
第一步:进入官站 https://www.netsarang.com/ 第二步:选中Free License
- 树莓派3_win10下使用"远程桌面连接"与树莓派通信(使用VNC实现连接后)
-----------------------------------------------------------学无止境------------------------------------- ...