P2801 教主的魔法
$N$ 太大了主席树过不了
考虑分块
对每个块内的元素排序,询问就对大块二分查找,对两边小的部分暴力枚举
修改时维护 $add[i]$ 标记,维护当前块内整块已经加的数
那么整块的就直接修改 $add$ ,两边小的部分就把那两个的块暴力修改然后重新排序
然后注意一下边界就完了
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
typedef long long ll;
inline int read()
{
int x=,f=; char ch=getchar();
while(ch<''||ch>'') { if(ch=='-') f=-; ch=getchar(); }
while(ch>=''&&ch<='') { x=(x<<)+(x<<)+(ch^); ch=getchar(); }
return x*f;
}
const int N=2e6+,M=2e3+,INF=1e9+;
int n,m;
int a[N];
int bel[N],L[M];//bel[i]存位置i所在的块,L[i]存第i个块的左端点
int blk[M][M],tmp[M],add[M];//blk就是分出来的块排序后的东西
inline void change(int l,int r,int k)//修改
{
if(bel[l]==bel[r])//要特判只有小块的情况
{
int tot=,be=bel[l];
for(int i=L[be];i<l;i++) tmp[++tot]=a[i];//把数直接扔到tmp里
for(int i=l;i<=r;i++) a[i]+=k,tmp[++tot]=a[i];//有修改要修改a[i]
for(int i=r+;i<L[be+];i++) tmp[++tot]=a[i];
sort(tmp+,tmp+tot+);
memcpy(blk[be],tmp,sizeof(tmp));//排序后扔给blk
}
int pl=bel[l-]+,pr=bel[r+]-,tot=;//找到整块
for(int i=pl;i<=pr;i++) add[i]+=k;
if(pl>bel[])//处理左边小块
{
for(int i=L[pl-];i<l;i++) tmp[++tot]=a[i];
for(int i=l;i<L[pl];i++) a[i]+=k,tmp[++tot]=a[i];
sort(tmp+,tmp+tot+);
memcpy(blk[pl-],tmp,sizeof(tmp));
}
if(pr<bel[n])//右边
{
for(int i=L[pr+];i<=r;i++) a[i]+=k,tmp[++tot]=a[i];
for(int i=r+;i<L[pr+];i++) tmp[++tot]=a[i];
sort(tmp+,tmp+tot+);
memcpy(blk[pr+],tmp,sizeof(tmp));
}
}
inline int query(int l,int r,int k)//处理询问
{
if(bel[l]==bel[r])//特判没有整块
{
int res=;
for(int i=l;i<=r;i++) if(a[i]>=k-add[bel[i]]) res++;
return res;
}
int pl=bel[l-]+,pr=bel[r+]-,res=;
for(int i=pl;i<=pr;i++)//对大块的二分
res+=(L[i+]-L[i]) -( lower_bound(blk[i]+ , blk[i]+(L[i+]-L[i])+ , k-add[i]) -blk[i])+;
for(int i=l;i<L[pl];i++) if(a[i]>=k-add[bel[i]]) res++;//剩下的暴力计算
for(int i=L[pr+];i<=r;i++) if(a[i]>=k-add[bel[i]]) res++;
return res;
}
int main()
{
n=read(),m=read(); int t=sqrt(n);
for(int i=;i<=n;i++)
{
bel[i]=(i-)/t+;
if(bel[i]!=bel[i-]) L[bel[i]]=i;
else L[bel[i]]=L[bel[i-]];
a[i]=read();
}
bel[n+]=bel[n]+; L[bel[n+]]=n+;//注意可能会访问到n+1
for(int i=;i<=bel[n];i++)//预处理blk
{
int tot=;
for(int j=L[i];j<L[i+];j++) tmp[++tot]=a[j];
sort(tmp+,tmp+tot+);
memcpy(blk[i],tmp,sizeof(tmp));
}
char s[]; int x,y,z;
while(m--)
{
scanf("%s",s); x=read(),y=read(),z=read();
if(s[]=='M') change(x,y,z);
else printf("%d\n",query(x,y,z));
}
return ;
}
P2801 教主的魔法的更多相关文章
- P2801 教主的魔法(分块)
P2801 教主的魔法 区间加法,区间查询 显然就是分块辣 维护一个按块排好序的数组. 每次修改依然是整块打标记,零散块暴力.蓝后对零散块重新排序. 询问时整块二分,零散块暴力就好辣 注意细节挺多和边 ...
- 洛谷 P2801 教主的魔法 解题报告
P2801 教主的魔法 题目描述 教主最近学会了一种神奇的魔法,能够使人长高.于是他准备演示给XMYZ信息组每个英雄看.于是N个英雄们又一次聚集在了一起,这次他们排成了一列,被编号为1.2.--.N. ...
- 洛谷——P2801 教主的魔法(线段树or分块)
P2801 教主的魔法 (1) 若第一个字母为“M”,则紧接着有三个数字L.R.W.表示对闭区间 [L, R] 内所有英雄的身高加上W. (2) 若第一个字母为“A”,则紧接着有三个数字L.R.C.询 ...
- P2801 教主的魔法 (线段树)
题目 P2801 教主的魔法 解析 成天做水题 线段树,第一问区间加很简单 第二问可以维护一个区间最大值和一个区间最小值,若C小于等于区间最小值,就加上区间长度,若C大于区间最大值,就加0 ps:求教 ...
- 洛谷P2801 教主的魔法 [分块,二分答案]
题目传送门 教主的魔法 题目描述 教主最近学会了一种神奇的魔法,能够使人长高.于是他准备演示给XMYZ信息组每个英雄看.于是N个英雄们又一次聚集在了一起,这次他们排成了一列,被编号为1.2.…….N. ...
- luogu P2801 教主的魔法
题目描述 教主最近学会了一种神奇的魔法,能够使人长高.于是他准备演示给XMYZ信息组每个英雄看.于是N个英雄们又一次聚集在了一起,这次他们排成了一列,被编号为1.2.…….N. 每个人的身高一开始都是 ...
- 洛谷 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 ...
- P2801 教主的魔法(分块入门)
两个月之前听yyr学长讲的分块,感觉是个很神奇的暴力,但到现在还是懵的一匹 #include<bits/stdc++.h> using namespace std; ; int belon ...
- 洛谷P2801 教主的魔法 分块
正解:分块 解题报告: 哇之前的坑还没填完就又写新博客? 不管不管,之前欠的两三篇题解大概圣诞节之前会再仔细想想然后重新写下题解趴,确实还挺难的感觉没有很好的理解呢QAQ还是太囫囵吞枣不求甚解了,这样 ...
随机推荐
- c语言学习笔记 if语句执行流程和关系运算符
回想现实生活中,我们会遇到这样的情况,如果下雨了就带伞上班,如果没下雨就不带伞上班,这是很正常的逻辑.程序是解决生活中的问题的,那么自然在程序中也需要这样的判断,当满足某个条件的时候做一件事情,这种东 ...
- 6.AND & OR 运算符
AND 和 OR 运算符用于基于一个以上的条件对记录进行过滤 AND 和 OR 运算符 AND 和 OR 可在 WHERE 子语句中把两个或多个条件结合起来. 如果第一个条件和第二个条件都成立,则 A ...
- laravel中的attach and detach toggle method
创建模型 post and user 以及 users , posts ,user_post(favorities)测试数据 在此可以看上一篇中的数据,本次测试数据利用的上一篇的数据.detach ...
- SVN下载地址及注意事项
SVN下载地址:VisualSVN:http://www.visualsvn.com/server/download 服务器端(添加仓库和用户)TortoiseSVN:http://torto ...
- Row_Number() OVER()函数使用举例
语法:ROW_NUMBER() OVER(PARTITION BY COLUMN ORDER BY COLUMN) 简单的说row_number()从1开始,为每一条分组记录返回一个数字,这里的ROW ...
- UVa 1625 Color Length (DP)
题意:给定两个序列,让你组成一个新的序列,让两个相同字符的位置最大差之和最小.组成方式只能从一个序列前部拿出一个字符放到新序列中. 析:这个题状态表示和转移很容易想到,主要是在处理上面,dp[i][j ...
- 史融资2.5亿的“自主国产”红芯浏览器,其实是个套壳Chrome
红芯浏览器 今天早上看到朋友发的浏览器图片,感觉很好奇,然后就看了下,感觉文章还不错,就转发了下,然后下载浏览器着实花了不小心思,最后文末添加了红芯浏览器转存在蓝奏云盘的下载连接了. 文章原文 今天又 ...
- 【Head First Java 读书笔记】(一)基本概念
Java的工作方式 你要做的事情就是会编写源代码 Java的程序结构 类存于源文件里面 方法存在类中 语句存于方法中 剖析类 当Java虚拟机启动执行时,它会寻找你在命令列中所指定的类,然后它会锁定像 ...
- SharePoint配置网站集的审核设置
配置网站集的审核设置 您可以使用 Microsoft SharePoint Server 2010 的审核功能来跟踪哪些用户对网站集的网站.内容类型.列表.库.列表项和库文件执行了哪些操作.了解谁对哪 ...
- 匿名函数和lamda表达式
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...