bzoj2989&&4170数列——二进制分组+主席树
题意的转化挺巧妙的
可以联想到曼哈顿距离!
并且,所谓的修改还要查询历史版本,并且修改之间不动只算一次,不就是给平面上加一个点吗?
看成(x,a[x])的点
就是一个菱形区域
转切比雪夫距离,变成矩形区域
所以
平面单点加,矩形查询和
1.cdq分治
2.树套树(离散化都不用)
3.二进制分组+主席树
这里,大炮打蚊子,用二进制分组来写
加入的点按操作二进制分组,每个组用主席树维护这个平面,查询在logn上查询,合并暴力重构,256MB又没有删除,所以重构完了把原来的树垃圾回收
注意:
主席树垃圾回收,从最后一个根开始,一个点不能删除两次,所以共用点打die标记,之后搜到返回即可。
代码:
写得很丑
其实不用vector,可以开数组,记录每个组的范围。每次sort,然后建树。
#include<bits/stdc++.h>
#define reg register int
#define il inline
#define numb (ch^'0')
#define mid ((l+r)>>1)
#define fi first
#define se second
#define mp(a,b) make_pair(a,b)
using namespace std;
typedef long long ll;
il void rd(int &x){
char ch;x=;bool fl=false;
while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
for(x=numb;isdigit(ch=getchar());x=x*+numb);
(fl==true)&&(x=-x);
}
namespace Miracle{
const int N=+;
const int U=;
int n,q;
pair<int,int>a[N];
int b[N];
char ch[];
struct node{
int ls,rs;
int sum;
void clear(){
ls=rs=sum=;
}
}t[*];
int tot;
int sta[N],top;
int del[*],dc;
bool die[*];
int nc(){
int r=dc?del[dc--]:++tot;
die[r]=;
t[r].clear();
// cout<<" r "<<r<<" "<<t[r].sum<<" "<<t[r].ls<<" "<<t[r].rs<<endl;
return r;
//return ++tot;
}
int cnt;
vector<pair<int,int> >mem[N];
vector<int>rt[N],pos[N];
bool cmp(pair<int,int>a,pair<int,int> b){//a<b?
if(a.fi==b.fi) return a.se<b.se;
return a.fi<b.fi;
}
void merge(int i,int j){
vector<pair<int,int> >tmp;
int l=,r=;
for(reg k=;k<=(int)mem[i].size()+(int)mem[j].size();++k){
if(l>=(int)mem[i].size()){
tmp.push_back(mem[j][r++]);
}else if(r>=(int)mem[j].size()){
tmp.push_back(mem[i][l++]);
}else if(cmp(mem[i][l],mem[j][r])){
tmp.push_back(mem[i][l++]);
}else{
tmp.push_back(mem[j][r++]);
}
}
mem[i]=tmp;
}
void upda(int &x,int y,int l,int r,int p){
if(!x) x=nc();
t[x].sum=t[y].sum+;
if(l==r){return;}
if(p<=mid){
t[x].rs=t[y].rs;upda(t[x].ls,t[y].ls,l,mid,p);
}else{
t[x].ls=t[y].ls;upda(t[x].rs,t[y].rs,mid+,r,p);
}
}
void remove(int x){
if(!x||die[x]) return;
remove(t[x].ls);remove(t[x].rs);
t[x].clear();
die[x]=;
del[++dc]=x;
}
int query(int x,int y,int l,int r,int L,int R){
//cout<<" query "<<x<<" "<<y<<" "<<l<<" "<<r<<" goal "<<L<<" "<<R<<endl;
//cout<<" sum "<<t[x].sum<<" and "<<t[y].sum<<endl;
if(L<=l&&r<=R){
return t[x].sum-t[y].sum;
}
int ret=;
if(L<=mid) ret+=query(t[x].ls,t[y].ls,l,mid,L,R);
if(mid<R) ret+=query(t[x].rs,t[y].rs,mid+,r,L,R);
return ret;
}
void bing(int A,int B){
//cout<<" merge "<<A<<" "<<B<<endl;
// cout<<mem[A].size()<<" and "<<mem[B].size()<<endl;
for(reg i=rt[A].size()-;i>=;--i)
remove(rt[A][i]);
for(reg i=rt[B].size()-;i>=;--i)
remove(rt[B][i]);
// cout<<" guibing "<<endl;
merge(A,B); rt[A].clear();pos[A].clear();
for(reg i=;i<(int)mem[A].size();++i){
if(i==){
rt[A].push_back();pos[A].push_back(mem[A][i].fi);
upda(rt[A][],,-U,U,mem[A][i].se);
}else{
if(mem[A][i-].fi==mem[A][i].fi){
int tmp=rt[A][rt[A].size()-];
rt[A][rt[A].size()-]=;
upda(rt[A][rt[A].size()-],tmp,-U,U,mem[A][i].se);
}else{
rt[A].push_back();pos[A].push_back(mem[A][i].fi);
upda(rt[A][rt[A].size()-],rt[A][rt[A].size()-],-U,U,mem[A][i].se);
}
}
}
}
int calc(int x1,int y1,int x2,int y2){
int ret=;
//cout<<" seventy-five "<<t[75].sum<<endl;
for(reg i=;i<=top;++i){
int id=sta[i];
// cout<<" id "<<id<<" mem "<<mem[id].size()<<" pos "<<pos[id].size()<<endl;
// cout<<" seventy-five "<<t[75].sum<<endl;
int k1=lower_bound(pos[id].begin(),pos[id].end(),y1)-pos[id].begin();
--k1;
int k2=upper_bound(pos[id].begin(),pos[id].end(),y2)-pos[id].begin();
--k2;
// cout<<k1<<" and "<<k2<<endl;
// cout<<" seventy-five "<<t[75].sum<<endl;
k1=k1<?:rt[id][k1];
k2=k2<?:rt[id][k2];
ret+=query(k2,k1,-U,U,x1,x2);
// cout<<" seventy-five "<<t[75].sum<<endl;
}
return ret;
}
int main(){
rd(n);rd(q);
int x;
for(reg i=;i<=n;++i){
rd(x);a[i]=mp(i+x,i-x);
b[i]=x;
}
// cout<<cmp(mp(3,-1),mp(6,-2))<<endl;
sort(a+,a+n+,cmp);
for(reg i=;i<=n;++i){
//cout<<"("<<a[i].se<<","<<a[i].fi<<")"<<endl;
++cnt;
mem[cnt].push_back(a[i]);
rt[cnt].push_back();
pos[cnt].push_back(a[i].fi);
upda(rt[cnt][],,-U,U,a[i].se);
sta[++top]=cnt;
while(top>&&mem[sta[top]].size()==mem[sta[top-]].size()){
bing(sta[top-],sta[top]);
--top;
}
}
// cout<<cnt<<" "<<top<<endl;
int k;
while(q--){
scanf("%s",ch+);
rd(x);rd(k);
if(ch[]=='Q'){
// cout<<" seventy-five "<<t[75].sum<<endl;
printf("%d\n",calc(x-b[x]-k,x+b[x]-k,x-b[x]+k,x+b[x]+k));
// cout<<" seventy-five "<<t[75].sum<<endl;
}else{
++cnt;
mem[cnt].push_back(mp(x+k,x-k));
rt[cnt].push_back();
pos[cnt].push_back(x+k);
upda(rt[cnt][],,-U,U,x-k);
sta[++top]=cnt;
while(top>&&mem[sta[top]].size()==mem[sta[top-]].size()){
bing(sta[top-],sta[top]);
--top;
}
b[x]=k;
/// cout<<" seventy-five "<<t[75].sum<<endl;
// cout<<cnt<<" "<<top<<endl;
}
}
return ;
} }
signed main(){
// freopen("data.in","r",stdin);
// freopen("my.out","w",stdout);
Miracle::main();
return ;
} /*
Author: *Miracle*
Date: 2019/2/24 9:42:39
*/
bzoj2989&&4170数列——二进制分组+主席树的更多相关文章
- [BZOJ 2989]数列(二进制分组+主席树)
[BZOJ 2989]数列(二进制分组+主席树) 题面 给定一个长度为n的正整数数列a[i]. 定义2个位置的graze值为两者位置差与数值差的和,即graze(x,y)=|x-y|+|a[x]-a[ ...
- 2019.01.21 bzoj2989: 数列(二进制分组+主席树)
传送门 二进制分组入门题. 主席树写错调题2h+2h+2h+体验极差. 题意简述:给一堆点,支持加入一个点,询问有多少个点跟(x,y)(x,y)(x,y)曼哈顿距离不超过kkk. 思路:题目要求的是对 ...
- Dynamic Rankings ZOJ - 2112(主席树+树状数组)
The Company Dynamic Rankings has developed a new kind of computer that is no longer satisfied with t ...
- 【BZOJ2989】数列(二进制分组,主席树)
[BZOJ2989]数列(二进制分组,主席树) 题面 BZOJ 权限题啊... Description 给定一个长度为n的正整数数列a[i]. 定义2个位置的graze值为两者位置差与数值差的和,即g ...
- BZOJ2989 数列(二进制分组)
这题其实可以cdq分治做,但是如果强制在线的话,这里有个牛逼方法叫二进制分组. 它的基本思想是把修改操作按二进制分组,遇到修改就在尾部加一个,并与之前的合并,比如之前有23(16+4+2+1)个,加了 ...
- UOJ46. 【清华集训2014】玄学 [线段树,二进制分组]
UOJ 思路 模拟赛出了这题,结果我没学过二进制分组--一波主席树然后空间就爆炸了-- 用线段树维护时间序列,每个节点维护\(a_i\to x_i\times a_i+b_i,i\in [1,n]\) ...
- CDOJ 1104 求两个数列的子列的交集 查询区间小于A的数有多少个 主席树
求两个数列的子列的交集 Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.uestc.edu.cn/#/problem/show/1104 ...
- 【BZOJ3821/UOJ46】玄学(二进制分组,线段树)
[BZOJ3821/UOJ46]玄学(二进制分组,线段树) 题面 BZOJ UOJ 题解 呜,很好的题目啊QwQ. 离线做法大概可以线段树分治,或者直接点记录左右两次操作时的结果,两个除一下就可以直接 ...
- Codeforces 960 二进制构造子序列 完全二叉树shift模拟 主席树/MAP DP
A #include <bits/stdc++.h> #define PI acos(-1.0) #define mem(a,b) memset((a),b,sizeof(a)) #def ...
随机推荐
- C#获取当前堆栈的各调用方法列表
在使用.NET编写的代码在debug时很容易进行排查和定位问题,一旦项目上线并出现问题的话那么只能依靠系统日志来进行问题排查和定位,但当项目复杂时,即各种方法间相互调用将导致要获取具体的出错方法或调用 ...
- WPF 录屏软件研发心得及思路分享(已结束开发)
最近由于工程需要开始研发基于Windows的自动录屏软件,很多细节很多功能需要处理,毕竟一个完美的录屏软件不是你随随便便就可以写出来的.首先参考了大部分的录屏软件,在研发的过程中遇到了很多的问题:比如 ...
- QQ聊天记录备份助手 v1.0——搜索、备份、恢复QQ聊天记录文件,重装系统必备
项目地址 https://github.com/guoyaohua/QQBackUp 开发环境 Netbean JAVA 功能描述 自动搜索硬盘中的QQ聊天记录文件 可选择的备份QQ数据记录 还原QQ ...
- keycloak 调研资料
1.https://www.keycloak.org/docs/latest/server_development/index.html 下载keycloak 2.https://gitee.com/ ...
- mac下查看和设置环境变量
1.查看环境变量 命令 env 2.修改环境变量 命令 cd ~ && ls -a && sudo vim .bashrc 编辑输入要添加的环境变量 3.s ...
- Hitchhiker 是一款开源的 Restful Api 测试工具
Hitchhiker 是一款开源的 Restful Api 测试工具 开源API测试工具 Hitchhiker v0.4更新 - 没有做不到,只有想不到 Hitchhiker 是一款开源的 Restf ...
- Hacked VisualSVN Server by PHP to allow user change password
index.php <?php$username = $_SERVER["PHP_AUTH_USER"]; //经过 AuthType Basic 认证的用户名$authed ...
- Win10 1803 Spring Creators update Consumer edition的版本记录
安装时可选择的版本列表 安装完之后的版本: 3. 时间线更新 4. Focus assistant
- PP学习笔记02
SPRO SAP参考IMG MM03 物料视图 生产计划编制 需求管理 已计划的独立需求 需求类型 策略组 定义策略 策略组 主要策略(独立需求 ) 客户需求类型 需求类 (计划标识符.消耗标识.需求 ...
- TF版本的Word2Vec和余弦相似度的计算
前几天一个同学在看一段代码,内容是使用gensim包提供的Word2Vec方法训练得到词向量,里面有几个变量code.count.index.point看不懂,就向我求助,我大概给他讲了下code是哈 ...