题面

学习二进制分组

题目本身可以看成二维平面上的问题,转成切比雪夫距离后就是矩形和了

二进制分组是将每个修改添加到末尾,然后从后往前二进制下进位合并,这样最多同时有$\log n$组,每个修改只会被合并$\log n$次。再用一个$log$代价在每次询问时把答案合并起来即可

 #include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
#define vpii vector<pair<int,int> >
using namespace std;
const int N=,M=1e7,K=,inf=1e9;
int n,m,nm,t1,t2,pt,pw,a[N],bin[M+],vis[M+];
int root[K][N],val[M+],son[M+][]; vpii ve[];
char rd[];
void Modify(int &nde,int lst,int l,int r,int tsk)
{
nde=bin[pt--],vis[nde]=false;
val[nde]=val[lst]+;
son[nde][]=son[lst][];
son[nde][]=son[lst][];
if(l==r) return; int mid=(l+r)>>;
if(tsk<=mid) Modify(son[nde][],son[lst][],l,mid,tsk);
else Modify(son[nde][],son[lst][],mid+,r,tsk);
}
void Delete(int nde,int l,int r)
{
if(vis[nde]) return;
bin[++pt]=nde,vis[nde]=true;
int mid=(l+r)>>;
Delete(son[nde][],l,mid);
Delete(son[nde][],mid+,r);
val[nde]=son[nde][]=son[nde][]=;
}
void Insert(int x,int y)
{
ve[++pw].push_back(make_pair(x,y));
Modify(root[pw][],root[pw][],,nm,y);
while(pw>&&ve[pw].size()==ve[pw-].size())
{
int t1=,t2=,sz=ve[pw].size(); vpii tmp;
for(int i=;i<=sz;i++) Delete(root[pw][i],,nm);
for(int i=;i<=sz;i++) Delete(root[pw-][i],,nm);
while(t1<sz||t2<sz)
if(t1<sz&&(t2==sz||ve[pw-][t1]<ve[pw][t2]))
tmp.push_back(ve[pw-][t1++]),Modify(root[pw-][t1+t2],root[pw-][t1+t2-],,nm,ve[pw-][t1-].second);
else
tmp.push_back(ve[pw][t2++]),Modify(root[pw-][t1+t2],root[pw-][t1+t2-],,nm,ve[pw][t2-].second);
ve[pw-]=tmp,ve[pw--].clear();
}
}
int Ask(int nl,int nr,int l,int r,int ll,int rr)
{
if(l>=ll&&r<=rr)
return val[nr]-val[nl];
else
{
int ret=,mid=(l+r)>>;
if(mid>=ll) ret+=Ask(son[nl][],son[nr][],l,mid,ll,rr);
if(mid<rr) ret+=Ask(son[nl][],son[nr][],mid+,r,ll,rr);
return ret;
}
}
int Query(int x,int y,int k)
{
int ret=;
for(int i=;i<=pw;i++)
{
int ll=lower_bound(ve[i].begin(),ve[i].end(),make_pair(x-k,))-ve[i].begin();
int rr=lower_bound(ve[i].begin(),ve[i].end(),make_pair(x+k,inf))-ve[i].begin();
ret+=Ask(root[i][ll],root[i][rr],,nm,max(y-k,),min(y+k,nm));
}
return ret;
}
int main()
{
scanf("%d%d",&n,&m);
vis[]=true,nm=;
for(int i=;i<=M;i++)
bin[++pt]=i,vis[i]=true;
for(int i=;i<=n;i++)
scanf("%d",&a[i]),Insert(a[i]+i,a[i]-i+n);
for(int i=;i<=m;i++)
{
scanf("%s%d%d",rd,&t1,&t2);
if(rd[]=='M') a[t1]=t2,Insert(t2+t1,t2-t1+n);
else printf("%d\n",Query(a[t1]+t1,a[t1]-t1+n,t2));
}
return ;
}

解题:BZOJ 2989 数列的更多相关文章

  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 2989: 数列

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

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

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

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

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

  6. bzoj 4303 数列

    bzoj 4303 数列 二维 \(KD-Tree\) 模板题. \(KD-Tree\) 虽然在更新和查询的方式上类似于线段树,但其本身定义是类似于用 \(splay/fhq\ treap\) 维护区 ...

  7. BZOJ 3142 数列(组合)

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

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

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

  9. bzoj 4305 数列的GCD

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

随机推荐

  1. Android Device Monitor 文件管理的常见问题 - z

    Android Device Monitor 是 Android Studio 中用于监测模拟器或真机运行状态的一款开发者工具.但开发者在使用它的过程中往往会遇到很多问题,尤其对于新手.本文分析了实际 ...

  2. 20155210 实验一 逆向与Bof基础

    20155210 实验一 逆向与Bof基础 实验内容 1.直接修改程序机器指令,改变程序执行流程 下载目标文件pwn1,反汇编 利用objdump -d pwn1对pwn1进行反汇编 得到: 8048 ...

  3. # 2017-2018-2 20155319『网络对抗技术』Exp6:信息收集与漏洞扫描

    2017-2018-2 20155319『网络对抗技术』Exp6:信息收集与漏洞扫描 实践内容 (1)各种搜索技巧的应用 (2)DNS IP注册信息的查询 (3)基本的扫描技术:主机发现.端口扫描.O ...

  4. 20155330 《网络攻防》 Exp3 免杀原理与实践

    20155330 <网络攻防> Exp3 免杀原理与实践 基础问题回答 杀软是如何检测出恶意代码的? 基于特征码.先对流行代码特征的提取,然后进行程序的比对,如果也检测到相应的特征码的程序 ...

  5. kali安装后的网络设置教程(必需)

    本文只适用于kali安装完成后的网络设置,使用NAT模式,关于桥接模式设置在完成本教程后,可以自行百度,教程有很多,但前提是你已经执行完了本教程才能进行进一步的设置(但有些人的kali是可以直接联网的 ...

  6. angularJs 技巧总结及最佳实践

    强烈建议通读官方wiki文档,里面包含了FAQ,最佳实践,深入理解最核心的Directive及Scope等文章, 基础 1. 使用ng-repeat指令,为防止重复值发生的错误.加上track by ...

  7. linuxC/C++面试问题总结整理

    linuxC/C++面试问题总结整理 因为一些原因重新找工作了,面的linux c/c++,这里把面试中经常碰到的问题总结一下. linuxC/C++面试问题总结整理 单元测试 关键字const 关键 ...

  8. 剑指offer——滑动窗口的最大值

    给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值.例如,如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一共存在6个滑动窗口,他们的最大值分别为{4,4,6,6,6, ...

  9. GTX1060 深度学习工具链

    通过试错,推荐GTX1060 WIN10的工具链记录如下: GPU: GTX 1060 6G OS: WIN10 CUDA:9.0 CuDNN:7.1.3 Tensorflow: Tensorflow ...

  10. PAT甲题题解-1052. Linked List Sorting (25)-排序

    三个注意点: 1.给出的n个节点并不一定都在链表中 2.最后一组样例首地址即为-1 3.输出地址的时候一直忘记前面要补0... #include <iostream> #include & ...