传送门

$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 教主的魔法的更多相关文章

  1. P2801 教主的魔法(分块)

    P2801 教主的魔法 区间加法,区间查询 显然就是分块辣 维护一个按块排好序的数组. 每次修改依然是整块打标记,零散块暴力.蓝后对零散块重新排序. 询问时整块二分,零散块暴力就好辣 注意细节挺多和边 ...

  2. 洛谷 P2801 教主的魔法 解题报告

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

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

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

  4. P2801 教主的魔法 (线段树)

    题目 P2801 教主的魔法 解析 成天做水题 线段树,第一问区间加很简单 第二问可以维护一个区间最大值和一个区间最小值,若C小于等于区间最小值,就加上区间长度,若C大于区间最大值,就加0 ps:求教 ...

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

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

  6. luogu P2801 教主的魔法

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

  7. 洛谷 P2801 教主的魔法

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

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

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

  9. P2801 教主的魔法(分块入门)

    两个月之前听yyr学长讲的分块,感觉是个很神奇的暴力,但到现在还是懵的一匹 #include<bits/stdc++.h> using namespace std; ; int belon ...

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

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

随机推荐

  1. AOP基本概念、AOP底层实现原理、AOP经典应用【事务管理、异常日志处理、方法审计】

    1 什么是AOP AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.AOP是OOP的延续,是软件 ...

  2. Django--admin后台

    需求 通过后台和models​操作数据库表 实现 1.后台中看到数据库中的表 app01/admin.py 1 2 from app01 import models admin.site.regist ...

  3. Django Rest Framework框架 ---- url控制器

    Django Rest Framework框架 ---- url控制器

  4. URL 与 URI

    http://localhost:8080/TEST_Servlet/ClientRequest/test?name=wr getRequestURL:http://localhost:8080/TE ...

  5. MATLAB读取写入文本数据最佳方法 | Best Method for Loading & Saving Text Data Using MATLAB

    MATLAB读取文件有很多方法.然而笔者在过去进行数据处理中,由于函数太多,相互混杂,与C#,Python等语言相比,反而认为读取文本数据比较麻烦.C#和Python等高级语言中,对于大部分的文本数据 ...

  6. ntroducing K-Pattern: A Rapid Way to Make CRUD Operations with Entity Framework

    Download Source Introduction Earlier in the last year I made a different approach to work on Entity ...

  7. Floyd-Warshall求图中任意两点的最短路径

    原创 除了DFS和BFS求图中最短路径的方法,算法Floyd-Warshall也可以求图中任意两点的最短路径. 从图中任取两点A.B,A到B的最短路径无非只有两种情况: 1:A直接到B这条路径即是最短 ...

  8. timer实现Grid自动换行(连续相同的id跳到下一行)

    private { Private declarations } FRow: Integer; procedure SetRow(const Value: Integer); public { Pub ...

  9. [.net 多线程]CountdownEvent

    System.Threading.CountdownEvent 是一个同步基元,它在收到一定次数的信号之后,将会解除对其等待线程的锁定.CountdownEvent在初始化时有一个初始计数量,在每个工 ...

  10. javascript js函数重名后面的覆盖前面的

    js 函数重名后面的覆盖前面的   var x = 1;    var y = 0;    var z = 0;    function add(n) { return n = n + 1; }    ...