洛谷 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; ...
随机推荐
- C#中在WebClient中使用post发送数据实现方法
很多时候,我们需要使用C#中的WebClient 来收发数据,WebClient 类提供向 URI 标识的任何本地.Intranet 或 Internet 资源发送数据以及从这些资源接收数据的公共方法 ...
- mac phpstorm 破解方法
方法参考如下链接: 来源:http://www.cnblogs.com/zyliang/p/6148960.html
- 基于设备树的led驱动程序
#include <linux/module.h> #include <linux/kernel.h> #include <linux/fs.h> #include ...
- DHT11资料
产品名:温湿度传感器 型号:DHT11 厂商:奥松电子 参数: 相对湿度: 分辨率:0.1%RH 16Bit 精度:25℃ 正负 %2 温度: 分辨率:0.1%RH 16 ...
- vuejs中的计算属性和监视
计算属性 1.在computed属性对象中定义计算属性的方法,在页面上使用{{方法名}}来显示计算结果 2.通过getter/setter实现对属性数据的显示和监视 3.计算属性存在缓存,多次读取只执 ...
- STL 入门 (17 暑假集训第一周)
快速全排列的函数 头文件<algorithm> next_permutation(a,a+n) ---------------------------------------------- ...
- java stream 处理分组后取每组最大
有一个需求功能:先按照某一字段分组,再按照另外字段获取最大的那个 Map<String, HitRuleConfig> configMap = configList.parallelStr ...
- easyui 验证动态添加和删除问题
$.extend($.fn.validatebox.methods, { remove: function(jq, newposition){ return jq.each(function(){ $ ...
- Can’t delete list item in Sharepoint2013
Today,I have meet a very strange error.When I attempt to delete a item from a list,I recieve an ...
- 去掉google play专为手机设计标识
google play上的应用默认都会有个“专为手机设计”的标识 有时应用明明已经针对平板作了优化,但为什么这个标识还在呢,如何去掉这个标识呢,其实只需要两个步骤就好了: 1. 标记为支持高分辨率 & ...