P2801 教主的魔法
时间:2019-03-24
本文章向大家介绍P2801 教主的魔法,主要包括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=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); } return x*f; } const int N=2e6+7,M=2e3+7,INF=1e9+7; 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=0,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+1;i<L[be+1];i++) tmp[++tot]=a[i]; sort(tmp+1,tmp+tot+1); memcpy(blk[be],tmp,sizeof(tmp));//排序后扔给blk } int pl=bel[l-1]+1,pr=bel[r+1]-1,tot=0;//找到整块 for(int i=pl;i<=pr;i++) add[i]+=k; if(pl>bel[1])//处理左边小块 { for(int i=L[pl-1];i<l;i++) tmp[++tot]=a[i]; for(int i=l;i<L[pl];i++) a[i]+=k,tmp[++tot]=a[i]; sort(tmp+1,tmp+tot+1); memcpy(blk[pl-1],tmp,sizeof(tmp)); } if(pr<bel[n])//右边 { for(int i=L[pr+1];i<=r;i++) a[i]+=k,tmp[++tot]=a[i]; for(int i=r+1;i<L[pr+2];i++) tmp[++tot]=a[i]; sort(tmp+1,tmp+tot+1); memcpy(blk[pr+1],tmp,sizeof(tmp)); } } inline int query(int l,int r,int k)//处理询问 { if(bel[l]==bel[r])//特判没有整块 { int res=0; for(int i=l;i<=r;i++) if(a[i]>=k-add[bel[i]]) res++; return res; } int pl=bel[l-1]+1,pr=bel[r+1]-1,res=0; for(int i=pl;i<=pr;i++)//对大块的二分 res+=(L[i+1]-L[i]) -( lower_bound(blk[i]+1 , blk[i]+(L[i+1]-L[i])+1 , k-add[i]) -blk[i])+1; for(int i=l;i<L[pl];i++) if(a[i]>=k-add[bel[i]]) res++;//剩下的暴力计算 for(int i=L[pr+1];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=1;i<=n;i++) { bel[i]=(i-1)/t+1; if(bel[i]!=bel[i-1]) L[bel[i]]=i; else L[bel[i]]=L[bel[i-1]]; a[i]=read(); } bel[n+1]=bel[n]+1; L[bel[n+1]]=n+1;//注意可能会访问到n+1 for(int i=1;i<=bel[n];i++)//预处理blk { int tot=0; for(int j=L[i];j<L[i+1];j++) tmp[++tot]=a[j]; sort(tmp+1,tmp+tot+1); memcpy(blk[i],tmp,sizeof(tmp)); } char s[7]; int x,y,z; while(m--) { scanf("%s",s); x=read(),y=read(),z=read(); if(s[0]=='M') change(x,y,z); else printf("%d\n",query(x,y,z)); } return 0; }
- 【Java入门提高篇】Day14 Java中的泛型初探
- 使用shell脚本快速得到主备关系(r9笔记第93天)
- 【Java入门提高篇】Day13 Java中的反射机制
- 仿腾讯课堂固定滚动列表ReactNative组件
- Golang通过socket与java通讯
- Java基础-day09-基础题-对象;类;封装
- 通过shell脚本得到数据库的基本信息(一)(r9笔记第89天)
- iOS设备唯一标识的前世今生
- python 生成内嵌式字典(dict)-案例从python提取内嵌json写入mongodb
- Golang语言打印九九乘法表
- AVFoundation 框架初探究(四)
- Data Guard跳归档恢复的实践(r9笔记第92天)
- AVFoundation 框架初探究(三)
- AVFoundation 框架初探究(二)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 明了 | MongoDB 外键的基本使用
- 优雅 | koa处理异常
- iOS开发之Context Menus
- 快速解释如何使用pandas的inplace参数
- bam格式转bigWig
- 46. Vue路由传参的基本使用
- H3C在端口同时配置MAC地址认证和802.1x
- proxmox notes
- Unix每分钟监控进程的状态
- webpack实战——资源输入与输出
- R语言读取 xlsx 和xls 文件
- pytest文档42-fixture参数化params
- 搭建node服务(三):使用TypeScript
- Antd for Vue使用Form组件报错You cannot set a form field before rendering
- IDEA配置Resin