bzoj 4303 数列

  • 二维 \(KD-Tree\) 模板题.
  • \(KD-Tree\) 虽然在更新和查询的方式上类似于线段树,但其本身定义是类似于用 \(splay/fhq\ treap\) 维护区间的二叉搜索树,没有加点删点,建树时将它建成平衡的就好了.
  • 这使得一个 \(node\) 的左子树管辖 \([l,mid-1]\) ,右子树管辖 \([mid+1,r]\) , \(mid\) 处的信息存在自己处,不要写混.
  • 对于 \(k\) 维的 \(KD-Tree\) ,它每次更新/查询的时间复杂度是 \(O(n^{1-\frac 1 k})\) .所以本题总时间复杂度为 \(O(m\sqrt n)\).
  • 在常数优化上有一个小技巧:若答案 \(ans\) 对 \(2^k\) 取模,可以直接输出 $ans&(P-1) $.本题 \(536870912=2^{29}\).
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mp make_pair
#define pii pair<int,int>
#define inf 0x7f7f7f7f
inline int read()
{
int x=0;
bool pos=1;
char ch=getchar();
for(;!isdigit(ch);ch=getchar())
if(ch=='-')
pos=0;
for(;isdigit(ch);ch=getchar())
x=x*10+ch-'0';
return pos?x:-x;
}
const int MAXN=5e4+10;
const int P=536870912;
inline int add(int a,int b)
{
return (a + b) ;
}
inline int mul(int a,int b)
{
return a * b ;
}
int n,m,Tp;
struct node{
int tp;//维护的维度
int mi[2],ma[2];//[x/y]的最小,最大值
int v[2];//坐标
int ls,rs;
int tagadd,tagmul;
int val,len,sum;
bool operator < (const node& rhs) const
{
return v[Tp]<rhs.v[Tp];//当前比较的维度,全局变量储存.
}
node()
{
ls=rs=0;
tagadd=0;
tagmul=1;
sum=0;
}
}Tree[MAXN];
#define root Tree[o]
#define lson Tree[Tree[o].ls]
#define rson Tree[Tree[o].rs]
void pushup(int o)
{
root.mi[0]=min(root.v[0],min(lson.mi[0],rson.mi[0]));
root.mi[1]=min(root.v[1],min(lson.mi[1],rson.mi[1]));
root.ma[0]=max(root.v[0],max(lson.ma[0],rson.ma[0]));
root.ma[1]=max(root.v[1],max(lson.ma[1],rson.ma[1]));
}
int BuildTree(int l,int r,int tp)
{
Tp=tp;
int mid=(l+r)>>1;
int o=mid;
nth_element(Tree+l,Tree+mid,Tree+r+1);
root.tp=tp;
root.len=r-l+1;
if(l<mid)
root.ls=BuildTree(l,mid-1,(tp+1)%2);
if(r>mid)
root.rs=BuildTree(mid+1,r,(tp+1)%2);
pushup(o);
return o;
}
void Modifiy_mul(int o,int mulv)
{
root.val=mul(root.val,mulv);
root.tagmul=mul(root.tagmul,mulv);
root.tagadd=mul(root.tagadd,mulv);
root.sum=mul(root.sum,mulv);
}
void Modifiy_add(int o,int addv)
{
root.val=add(root.val,addv);
root.tagadd=add(root.tagadd,addv);
root.sum=add(root.sum,mul(root.len,addv));
}
void pushdown(int o)
{
if(root.tagmul!=1)
{
Modifiy_mul(root.ls,root.tagmul);
Modifiy_mul(root.rs,root.tagmul);
root.tagmul=1;
}
if(root.tagadd!=0)
{
Modifiy_add(root.ls,root.tagadd);
Modifiy_add(root.rs,root.tagadd);
root.tagadd=0;
}
}
void update(int o,int L,int R,int mulv,int addv)//修改第Tp维
{
if(L>root.ma[Tp] || R<root.mi[Tp])
return;
if(L<=root.mi[Tp] && root.ma[Tp]<=R)
{
Modifiy_mul(o,mulv);
Modifiy_add(o,addv);
return;
}
pushdown(o);
if(L<=root.v[Tp] && root.v[Tp]<=R)
{
root.val=mul(root.val,mulv);
root.val=add(root.val,addv);
}
pushdown(o);
update(root.ls,L,R,mulv,addv);
update(root.rs,L,R,mulv,addv);
root.sum=add(lson.sum,rson.sum);
root.sum=add(root.sum,root.val);
}
int query(int o,int L,int R)
{
if(L>root.ma[Tp] || R<root.mi[Tp])
return 0;
if(L<=root.mi[Tp] && root.ma[Tp]<=R)
return root.sum;
pushdown(o);
int res=0;
if(root.ls)
res=add(res,query(root.ls,L,R));
if(root.rs)
res=add(res,query(root.rs,L,R));
if(L<=root.v[Tp] && root.v[Tp]<=R)
res=add(res,root.val);
return res;
}
int rt;
void init()
{
Tree[0].ma[0]=Tree[0].ma[1]=-inf;
Tree[0].mi[0]=Tree[0].mi[1]=inf;
for(int i=1;i<=n;++i)
{
Tree[i].v[0]=i;
Tree[i].v[1]=read();
}
rt=BuildTree(1,n,0);
}
int main()
{
n=read(),m=read();
init();
while(m--)
{
int op=read();
int l,r,x,y;
if(op==0)
{
l=read(),r=read(),x=read(),y=read();
Tp=0;
update(rt,l,r,x,y);
}
else if(op==1)
{
l=read(),r=read(),x=read(),y=read();
Tp=1;
update(rt,l,r,x,y);
}
else if(op==2)
{
l=read(),r=read();
Tp=0;
printf("%d\n",query(rt,l,r)&(P-1));
}
else
{
l=read(),r=read();
Tp=1;
printf("%d\n",query(rt,l,r)&(P-1));
}
}
return 0;
}

bzoj 4303 数列的更多相关文章

  1. [BZOJ 2989]数列(二进制分组+主席树)

    [BZOJ 2989]数列(二进制分组+主席树) 题面 给定一个长度为n的正整数数列a[i]. 定义2个位置的graze值为两者位置差与数值差的和,即graze(x,y)=|x-y|+|a[x]-a[ ...

  2. [BZOJ 2989]数列(CDQ 分治+曼哈顿距离与切比雪夫距离的转化)

    [BZOJ 2989]数列(CDQ 分治) 题面 给定一个长度为n的正整数数列a[i]. 定义2个位置的graze值为两者位置差与数值差的和,即graze(x,y)=|x-y|+|a[x]-a[y]| ...

  3. BZOJ 3142 数列(组合)

    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=3142 题意:给出n,K,m,p.求有多少长度为K的序列A,满足:(1)首项为正整数:(2 ...

  4. BZOJ 4305: 数列的GCD( 数论 )

    对于d, 记{ai}中是d的倍数的数的个数为c, 那么有: 直接计算即可,复杂度O(NlogN+MlogM) --------------------------------------------- ...

  5. bzoj 4305 数列的GCD

    LINK:数列的GCD 题意: 给出一个长度为N的数列{a[n]},1<=a[i]<=M(1<=i<=N). 现在问题是,对于1到M的每个整数d,有多少个不同的数列b[1], ...

  6. bzoj 2989: 数列

    LINK:数列 需要动一点脑子 考虑查询 暴力显然不行 考虑把绝对值拆开. 当x<=y ax<=ay时 有 y-x+ay-ax<=k x+ax>=y+ay-k 可以发现在满足前 ...

  7. BZOJ 2989: 数列/4170: 极光

    题解: n倍经验题 首先比较容易想到的是对绝对值分类讨论 然后是4维偏序 1.查询和修改顺序 2.x>y 3.a[x]>a[y] 4.(x+a[x])-(y+a[y])<=k 这样是 ...

  8. 解题:BZOJ 2989 数列

    题面 学习二进制分组 题目本身可以看成二维平面上的问题,转成切比雪夫距离后就是矩形和了 二进制分组是将每个修改添加到末尾,然后从后往前二进制下进位合并,这样最多同时有$\log n$组,每个修改只会被 ...

  9. BZOJ #2989. 数列 [树套树]

    考虑转化问题模型,这个没必要可持久化,直接加点就可以了,还不用删点 每次的问题是求 曼哈顿距离,变成切比雪夫距离然后求解 然后我们考虑将这玩意旋转 45度, 然后原坐标的 \((x,y)\) 会变成 ...

随机推荐

  1. LA 5713 秦始皇修路

    https://vjudge.net/problem/UVALive-5713 题意: 秦朝有n个城市,需要修建一些道路使得任意两个城市之间都可以连通.道士徐福声称他可以用法术修路,不花钱,也不用劳动 ...

  2. JavaScript对象、JSON对象、JSON字符串的区别

    一.首先看下什么是JSON JSON:JavaScript Object Natation,JavaScript对象的表现形式,已经发展成一种轻量级的数据交换格式. JavaScript对象的表现形式 ...

  3. php获取经纬度

    <?php header("content-type:text/html;charset=utf-8"); function ipjwd() { $getIp=$_SERVE ...

  4. linux文件的一些特殊权限

    一些特殊权限 虽然我们通常看到一个八进制的权限掩码用三位数字来表示,但是从技术层面 上来讲,用四位数字来表示它更确切些. 为什么呢?因为,除了读取,写入,和执 行权限之外,还有其它的,较少用到的权限设 ...

  5. NoSQL&&Redis介绍

    再说Redis之前,想先说一下NoSQL.在最早的单机时代,随着数据的增加一台机器可能放不下了.同时索引占用的内存空间也会越来越大.对请求的读写操作影响很大.于是就在数据库之前增加了一层保护层 — 缓 ...

  6. angular之自定义 directive

    1,指令的创建至少需要一个带有@Directive装饰器修饰的控制器类.@Directive装饰器指定了一个选择器名称,用于指出与此指令相关联的属性的名字. 2,创建一个highlight.direc ...

  7. Mercurial的使用心得

    本文发表地址:http://www.xiabingbao.com/mercurial/2015/01/22/mercurial-understanding/ 本人接触版本控制的历史 在很久很久以前,我 ...

  8. js中中括号,大括号使用详解

    js中中括号,大括号使用详解 一.总结 一句话总结:{ } 是一个对象,[ ] 是一个数组 1.js大括号{}表示什么意思? 对象 { } 大括号,表示定义一个对象,大部分情况下要有成对的属性和值,或 ...

  9. 百度地图API学习总结

    常用技术   1.创建地图: var map = new BMap.Map("divid"); 2.创建坐标点:var point = new BMap.Point("经 ...

  10. 到底啥是平台,到底啥是中台?李鬼太多,不得不说(ZT)

    (1)哪些不是中台,而是应该叫平台 做开发,有所谓的三层技术架构:前端展示层.中间逻辑层.后端数据层.我们现在讲的中台不在这个维度上. 做开发,还有所谓的技术中间件.一开始我们没有中间件的概念,只有操 ...