#K-D Tree#BZOJ 4303 数列
分析
将 \((i,p_i)\) 视为一个点,那么相当于对横坐标或纵坐标对应的点区间乘、区间加或者区间求和,
把这些点丢到 K-D Tree 上,维护最小/大横/纵坐标,如果当前区间点在范围内直接打懒标记,否则暴力修改,时间复杂度 \(O(m\sqrt{n})\)
代码
#include <cstdio>
#include <cctype>
#include <algorithm>
#include <queue>
using namespace std;
const int N=50011,lim=536870911;
int ran,root,n,m;
int iut(){
int ans=0; char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=ans*10+c-48,c=getchar();
return ans;
}
void print(int ans){
if (ans>9) print(ans/10);
putchar(ans%10+48);
}
int min(int a,int b){return a<b?a:b;}
int max(int a,int b){return a>b?a:b;}
struct rec{
int p[2],w;
bool operator <(const rec &t)const{
return p[ran]<t.p[ran];
}
};
struct KD_Tree{
int mn[N][2],mx[N][2],son[N][2],w[N],Lazy[N],lazy[N],len[N]; rec p[N];
void pup(int now){
for (int i=0;i<2;++i){
mn[now][i]=mx[now][i]=p[now].p[i];
if (son[now][0]){
mn[now][i]=min(mn[now][i],mn[son[now][0]][i]);
mx[now][i]=max(mx[now][i],mx[son[now][0]][i]);
}
if (son[now][1]){
mn[now][i]=min(mn[now][i],mn[son[now][1]][i]);
mx[now][i]=max(mx[now][i],mx[son[now][1]][i]);
}
}
}
void pLazy(int now,int z){
Lazy[now]=(1ll*Lazy[now]*z)&lim;
lazy[now]=(1ll*lazy[now]*z)&lim;
w[now]=(1ll*w[now]*z)&lim;
p[now].w=(1ll*p[now].w*z)&lim;
}
void plazy(int now,int z){
lazy[now]=(lazy[now]+z)&lim;
w[now]=(w[now]+1ll*z*len[now])&lim;
p[now].w=(p[now].w+z)&lim;
}
int build(int l,int r,int Ran){
if (l>r) return 0;
int mid=(l+r)>>1;
ran=Ran,nth_element(p+l,p+mid,p+1+r);
son[mid][0]=build(l,mid-1,Ran^1);
son[mid][1]=build(mid+1,r,Ran^1);
pup(mid),Lazy[mid]=1,len[mid]=r-l+1;
return mid;
}
void update(int now,int l,int r,int x,int y,int opt){
if (r<mn[now][opt]||l>mx[now][opt]) return;
if (l<=mn[now][opt]&&mx[now][opt]<=r){
pLazy(now,x),plazy(now,y);
return;
}
if (Lazy[now]!=1){
if (son[now][0]) pLazy(son[now][0],Lazy[now]);
if (son[now][1]) pLazy(son[now][1],Lazy[now]);
Lazy[now]=1;
}
if (lazy[now]){
if (son[now][0]) plazy(son[now][0],lazy[now]);
if (son[now][1]) plazy(son[now][1],lazy[now]);
lazy[now]=0;
}
if (l<=p[now].p[opt]&&p[now].p[opt]<=r) p[now].w=(1ll*p[now].w*x+y)&lim;
if (son[now][0]) update(son[now][0],l,r,x,y,opt);
if (son[now][1]) update(son[now][1],l,r,x,y,opt);
w[now]=(w[son[now][0]]+w[son[now][1]]+p[now].w)&lim;
}
int query(int now,int l,int r,int opt){
if (r<mn[now][opt]||l>mx[now][opt]) return 0;
if (l<=mn[now][opt]&&mx[now][opt]<=r) return w[now];
if (Lazy[now]!=1){
if (son[now][0]) pLazy(son[now][0],Lazy[now]);
if (son[now][1]) pLazy(son[now][1],Lazy[now]);
Lazy[now]=1;
}
if (lazy[now]){
if (son[now][0]) plazy(son[now][0],lazy[now]);
if (son[now][1]) plazy(son[now][1],lazy[now]);
lazy[now]=0;
}
int ans=0;
if (l<=p[now].p[opt]&&p[now].p[opt]<=r) ans+=p[now].w;
if (son[now][0]) ans+=query(son[now][0],l,r,opt);
if (son[now][1]) ans+=query(son[now][1],l,r,opt);
return ans&lim;
}
}Tre;
int main(){
n=iut(),m=iut();
for (int i=1;i<=n;++i) Tre.p[i]=(rec){i,iut(),0};
root=Tre.build(1,n,0);
for (int i=1;i<=m;++i){
int opt=iut(),l=iut(),r=iut();
if (opt<2){
int x=iut(),y=iut();
Tre.update(root,l,r,x,y,opt);
}else print(Tre.query(root,l,r,opt-2)),putchar(10);
}
return 0;
}
#K-D Tree#BZOJ 4303 数列的更多相关文章
- bzoj 4303 数列
bzoj 4303 数列 二维 \(KD-Tree\) 模板题. \(KD-Tree\) 虽然在更新和查询的方式上类似于线段树,但其本身定义是类似于用 \(splay/fhq\ treap\) 维护区 ...
- [BZOJ 2989]数列(二进制分组+主席树)
[BZOJ 2989]数列(二进制分组+主席树) 题面 给定一个长度为n的正整数数列a[i]. 定义2个位置的graze值为两者位置差与数值差的和,即graze(x,y)=|x-y|+|a[x]-a[ ...
- [BZOJ 2989]数列(CDQ 分治+曼哈顿距离与切比雪夫距离的转化)
[BZOJ 2989]数列(CDQ 分治) 题面 给定一个长度为n的正整数数列a[i]. 定义2个位置的graze值为两者位置差与数值差的和,即graze(x,y)=|x-y|+|a[x]-a[y]| ...
- bzoj 2989: 数列
LINK:数列 需要动一点脑子 考虑查询 暴力显然不行 考虑把绝对值拆开. 当x<=y ax<=ay时 有 y-x+ay-ax<=k x+ax>=y+ay-k 可以发现在满足前 ...
- BZOJ 3142 数列(组合)
题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=3142 题意:给出n,K,m,p.求有多少长度为K的序列A,满足:(1)首项为正整数:(2 ...
- BZOJ 4305: 数列的GCD( 数论 )
对于d, 记{ai}中是d的倍数的数的个数为c, 那么有: 直接计算即可,复杂度O(NlogN+MlogM) --------------------------------------------- ...
- AC日记——Count on a tree bzoj 2588
Description 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中lastans是上一个询问的答案,初始 ...
- bzoj 4305 数列的GCD
LINK:数列的GCD 题意: 给出一个长度为N的数列{a[n]},1<=a[i]<=M(1<=i<=N). 现在问题是,对于1到M的每个整数d,有多少个不同的数列b[1], ...
- 【ZJOI2013】k大数查询 BZOJ 3110
Description 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c 如果是2 a b c形式,表示询问从第a个位置到第b个位 ...
- BZOJ 2989: 数列/4170: 极光
题解: n倍经验题 首先比较容易想到的是对绝对值分类讨论 然后是4维偏序 1.查询和修改顺序 2.x>y 3.a[x]>a[y] 4.(x+a[x])-(y+a[y])<=k 这样是 ...
随机推荐
- 利用VkKeyScanA判断大写字母
string bind = "Hello"; for (int i = 0; i < bind.length(); i++) { short ch = VkKeyScanA( ...
- leetcode 将有序数组转换为二叉搜索树
给你一个整数数组 nums ,其中元素已经按 升序 排列,请你将其转换为一棵 高度平衡 二叉搜索树. 高度平衡 二叉树是一棵满足「每个节点的左右两个子树的高度差的绝对值不超过 1 」的二叉树. 示例 ...
- file.deleteOnExit()与file.delete()的区别
之前踩过一个坑,下载过的文件在我第二次打开app的时候奇迹的找不到了.难道是没有下载成功?为此我特地查看了我的本地文件路径的目录.事实证明文件的确是下载到了本地路径下,但是第二次进入app的时候,路径 ...
- dotnet nuget的命令行上传(推送/发布)包到Nexus 3
1.让Visual Studio在生成的时候也生成NuGet的包 在项目上点右键,选"属性",然后设置生成的时候制作NuGet的包. 英文版在这里打勾: 中文版在这里打勾: 重新生 ...
- 【Azure Developer】Python 读取 json文件及过滤出需要的结果
问题描述 首先,有名为 campsites.json 的JSON数据文件,数据格式为 { "type": "FeatureCollection", " ...
- 【Azure Redis 缓存】VM 里的 Redis 能直接迁移到 Azure Cache for Redis ? 需要改动代码吗?
问题描述 原来部署在VM 里的 Redis 能直接迁移到 Azure Cache for Redis? 需要改动代码吗? 问题解答 以上问题需要从两个方面来解答. 第一:VM中Redis的数据转移到 ...
- 固态硬盘使用f2fs作为根分区安装linux
目录 前言 碰到的问题 对策 我的实际操作步骤 0.警告 1. 准备 2. 分区 3. 使用网络安装debian10 4. 备份根分区 5. 修改固态硬盘linux根分区为f2fs 6.恢复备份 7. ...
- Nebula Graph|信息图谱在携程酒店的应用
本文首发于 Nebula Graph Community 公众号 对于用户的每一次查询,都能根据其意图做到相应的场景和产品的匹配",是携程酒店技术团队的目标,但实现这个目标他们遇到了三大问题 ...
- 用 NetworkX + Gephi + Nebula Graph 分析<权力的游戏>人物关系(上篇)
我们都知道<权利的游戏>在全世界都很多忠实的粉丝,除去你永远不知道剧情下一秒谁会挂这种意外"惊喜",当中复杂交错的人物关系也是它火爆的原因之一,而本文介绍如何通过 Ne ...
- 为什么带NOLOCK的查询语句还会造成阻塞
背景 客户反映HIS数据库在11点出现了长时间的阻塞,直到手动KILL掉阻塞的源头.请我们协助分析原因,最终定位到.NET程序中使用的SqlDataReader未正常关闭导致. 现象 登录SQL专家云 ...