[KDTree]数列
describtion
给你一个序列,每个序列有编号(它本身的位置),标识符,数值。
有4种操作
op=0:l,r,x,y将编号在[l,r]的数值x+y
op=1:l,r,x,y将标识在[l,r]的数值x+y
op=2:l,r将编号在[l,r]的数值和
op=3:l,r将标识在[l,r]的数值和
solution
kd-tree魔板……
维护两维
修改和线段树一样打标记即可。
还是写了很久
code
点击查看代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5;
const int mod=536870912;
int idx,op,n,m;
ll M,A;
struct data {
int z[2];
bool operator<(const data &u) const{return z[idx]<u.z[idx];}
}a[N];
struct node {int mid,mn[2],mx[2],sz;ll val,add=0,mul=1,sum=0;}T[N];
struct kd_tree {
int nd,ls[N],rs[N];
void Build(int x,int l,int r) {
idx^=1;int idt(idx);
int mid=(l+r)>>1;
T[x].mid=mid;T[x].sz=1;
nth_element(a+l,a+mid,a+r+1);
T[x].mn[0]=T[x].mx[0]=a[mid].z[0];T[x].mn[1]=T[x].mx[1]=a[mid].z[1];
if(l!=mid) {
ls[x]=++nd;int L(ls[x]);
Build(nd,l,mid-1),idx=idt;
T[x].mn[0]=min(T[x].mn[0],T[L].mn[0]),T[x].mn[1]=min(T[x].mn[1],T[L].mn[1]);
T[x].mx[0]=max(T[x].mx[0],T[L].mx[0]),T[x].mx[1]=max(T[x].mx[1],T[L].mx[1]);
T[x].sz+=T[L].sz;
}
if(r!=mid) {
rs[x]=++nd;int R(rs[x]);
Build(nd,mid+1,r);
T[x].mn[0]=min(T[x].mn[0],T[R].mn[0]),T[x].mn[1]=min(T[x].mn[1],T[R].mn[1]);
T[x].mx[0]=max(T[x].mx[0],T[R].mx[0]),T[x].mx[1]=max(T[x].mx[1],T[R].mx[1]);
T[x].sz+=T[R].sz;
}
// printf("%d pos=(%d,%d) z0:[%d,%d] z1:[%d,%d]\n",x,a[mid].z[0],a[mid].z[1],T[x].mn[0],T[x].mx[0],T[x].mn[1],T[x].mx[1]);
}
void mk_tree() {
++nd;idx=0;
Build(1,1,n);
}
inline void Up_mul(int x,ll w) {
T[x].mul=T[x].mul*w%mod;T[x].add=T[x].add*w%mod;
T[x].val=T[x].val*w%mod;T[x].sum=T[x].sum*w%mod;
}
inline void Up_add(int x,ll w) {
T[x].add=(T[x].add+w)%mod;
T[x].sum=(T[x].sum+T[x].sz*w)%mod;T[x].val=(T[x].val+w)%mod;
}
void P_dw(int x) {
if(T[x].mul!=1) {
if(ls[x])Up_mul(ls[x],T[x].mul);
if(rs[x])Up_mul(rs[x],T[x].mul);
T[x].mul=1;
}
if(T[x].add) {
if(ls[x])Up_add(ls[x],T[x].add);
if(rs[x])Up_add(rs[x],T[x].add);
T[x].add=0;
}
}
void P_up(int x) {T[x].sum=(T[ls[x]].sum+T[rs[x]].sum+T[x].val)%mod;}
void Update(int x,int l,int r) {
if(T[x].mx[op]<l||T[x].mn[op]>r) return;
if(T[x].mn[op]>=l&&T[x].mx[op]<=r) {Up_mul(x,M),Up_add(x,A);return;}
P_dw(x);
int pz(a[T[x].mid].z[op]);
if(pz>=l&&pz<=r) {T[x].val=(T[x].val*M+A)%mod;}
if(ls[x]) Update(ls[x],l,r);
if(rs[x]) Update(rs[x],l,r);
P_up(x);
}
ll Ask(int x,int l,int r) {
if(T[x].mx[op]<l||T[x].mn[op]>r) return 0;
if(l<=T[x].mn[op]&&T[x].mx[op]<=r) {return T[x].sum;}
P_dw(x);
ll res(0);int pz(a[T[x].mid].z[op]);
if(pz>=l&&pz<=r) {res=T[x].val;}
if(ls[x]) res=(res+Ask(ls[x],l,r))%mod;
if(rs[x]) res=(res+Ask(rs[x],l,r))%mod;
return res;
}
}KD;
int main() {
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) {a[i].z[0]=i;scanf("%d",&a[i].z[1]);}
KD.mk_tree();
for(int i=1;i<=m;i++) {
int opt,l,r;
scanf("%d%d%d",&opt,&l,&r);
if(!opt) {op=0;scanf("%lld%lld",&M,&A);KD.Update(1,l,r);}
else if(opt==1) {op=1;scanf("%lld%lld",&M,&A);KD.Update(1,l,r);}
else if(opt==2) {op=0;printf("%lld\n",KD.Ask(1,l,r));}
else if(opt==3) {op=1;printf("%lld\n",KD.Ask(1,l,r));}
}
return 0;
}

[KDTree]数列的更多相关文章
- 【BZOJ2989】数列 kd-tree
[BZOJ2989]数列 Description 给定一个长度为n的正整数数列a[i]. 定义2个位置的graze值为两者位置差与数值差的和,即graze(x,y)=|x-y|+|a[x]-a[y]| ...
- 【bzoj2989】数列 KD-tree+旋转坐标系
题目描述 给定一个长度为n的正整数数列a[i]. 定义2个位置的graze值为两者位置差与数值差的和,即graze(x,y)=|x-y|+|a[x]-a[y]|. 2种操作(k都是正整数): 1.Mo ...
- bzoj2989 数列(KDTree)
bzoj2989 数列(KDTree) bzoj 该说不愧是咱,一个月才水一篇题解然后还水的一批 题目描述: 给定一个长度为n的正整数数列a[i]. 定义2个位置的graze值为两者位置差与数值差的和 ...
- [JZOJ3615]【NOI2014模拟】数列(平面几何+二维线段树)
Description 给定一个长度为n的正整数数列a[i]. 定义2个位置的f值为两者位置差与数值差的和,即f(x,y)=|x-y|+|a[x]-a[y]|. 你需要写一个程序支持2种操作(k都是正 ...
- bzoj 4303 数列
bzoj 4303 数列 二维 \(KD-Tree\) 模板题. \(KD-Tree\) 虽然在更新和查询的方式上类似于线段树,但其本身定义是类似于用 \(splay/fhq\ treap\) 维护区 ...
- BZOJ_2989_数列&&BZOJ_4170_极光_KDTree
BZOJ_2989_数列&&BZOJ_4170_极光_KDTree Description "若是万一琪露诺(俗称rhl)进行攻击,什么都好,冷静地回答她的问题来吸引她.对方 ...
- bzoj 2989: 数列
LINK:数列 需要动一点脑子 考虑查询 暴力显然不行 考虑把绝对值拆开. 当x<=y ax<=ay时 有 y-x+ay-ax<=k x+ax>=y+ay-k 可以发现在满足前 ...
- C#求斐波那契数列第30项的值(递归和非递归)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- BZOJ1500[NOI2005]维修数列
Description Input 输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目.第2行包含N个数字,描述初始时的数列.以下M行,每行一 ...
随机推荐
- 从kill-chain的角度检测APT攻击
前言 最近一直在考虑如何结合kill chain检测APT攻击.出发点是因为尽管APT是一种特殊.高级攻击手段,但是它还是会具有攻击的common feature,只要可以把握住共同特征,就能进行检测 ...
- EMS查看邮箱容量限制的方法
以Exchange管理员身份打开EMS控制台.在PowerShell命令行提示符下,输入以下命令. Get-MailboxDatabase | FL name,IssueWarningQuota,Pr ...
- 将本地项目上传到gitLab操作
在设置好SSH之后,执行下面的操作即可完成: git init // 初始化git status //查看提交文件状态git remote add origin git地址 // 连接 ...
- nodeJs入门的第一节课
nodejs是什么? nodejs的架构模式以及优缺点 nodejs异步IO nodejs事件驱动 nodejs单线程 nodejs应用场景 一.nodejs是什么? 1.1nodejs是一个开源的. ...
- python循环与基本数据类型内置方法
今天又是充满希望的一天呢 一.python循环 1.wuile与else连用 当while没有被关键'break'主动结束的情况下 正常结束循环体代码之后会执行else的子代码 "" ...
- 深入剖析 RocketMQ 源码 - 负载均衡机制
RocketMQ作为一款流行的消息中间件在各大互联网应用广泛,本文主要分析RocketMq在消息生产和消费过程中的负载均衡机制,并创新提出消费端负载均衡策略的改写以实现固定IP消费的可能.
- 【LeetCode】358.K 距离间隔重排字符串
358.K 距离间隔重排字符串 知识点:哈希表:贪心:堆:队列 题目描述 给你一个非空的字符串 s 和一个整数 k,你要将这个字符串中的字母进行重新排列,使得重排后的字符串中相同字母的位置间隔距离至少 ...
- angular.js中 路由 用法及概念
在开讲之前,首先谈谈APP应用.平时我们用的app总是多页面,如果用原生安卓或者苹果,那当然很流畅啦.但是当我们用一般的html页面做移动端,简单时候我们可以用<a href="&qu ...
- bootStrap简要和学习笔记
bootStrap简要和学习笔记前端在学些了html.css.JavaScript三件套后,我们感觉前端变数太多了,需要创造力来设计一些可能经常使用的界面啊.按钮样式啊等,也就有了一些前端的框架,那何 ...
- XCTF练习题---MISC---Training-Stegano-1
XCTF练习题---MISC---Training-Stegano-1 flag:steganoI 解题步骤: 1.观察题目,下载附件 2.打开下载的图片文件,发现就是一个点,修改文件扩展名,还是说查 ...