BZOJ - 2957 (分块/线段树)
本质是维护斜率递增序列。
用分块的方法就是把序列分成sqrt(n)块,每个块分别用一个vector维护递增序列。查询的时候遍历所有的块,同时维护当前最大斜率,二分找到每个块中比当前最大斜率大的那个点。修改的时候只需要修改点所在的那个块即可。复杂度$O(m\sqrt nlogn)$
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
const int N=1e5+;
int n,m,h[N],in[N],L[N],R[N],sqrtn,n2;
vector<db> v[]; int main() {
scanf("%d%d",&n,&m),sqrtn=sqrt(n+0.5);
for(int i=; i<=n; ++i)L[i]=-;
for(int i=; i<=n; ++i) {
in[i]=i/sqrtn;
if(!~L[in[i]])L[in[i]]=i;
R[in[i]]=i;
n2=max(n2,in[i]);
}
while(m--) {
int x,y;
scanf("%d%d",&x,&y);
h[x]=y;
v[in[x]].clear();
for(int i=L[in[x]]; i<=R[in[x]]; ++i) {
db t=(db)h[i]/i;
if(v[in[x]].size()&&v[in[x]].back()>t)continue;
v[in[x]].push_back(t);
}
db mx=;
int ans=;
for(int i=; i<=n2; ++i) {
int j=upper_bound(v[i].begin(),v[i].end(),mx)-v[i].begin();
ans+=v[i].size()-j;
if(v[i].size())mx=max(mx,v[i].back());
}
printf("%d\n",ans);
}
return ;
}
用线段树的方法是利用“每个区间的递增序列长度为左区间的递增序列长度加上右区间中比左区间最大值大的递增序列长度”的性质来维护递增序列长度。左区间的递增序列长度可以直接加上,右区间的与左区间的最大值有关,姑且用$qry(mx[ls],rs)$来表示($mx[ls]$代表左区间最大值),则有区间合并公式:$cnt[u]=cnt[ls]+qry(mx[ls],rs)$。
然后就是$qry(mx[ls],rs)$的计算问题了。设$qry(x,u)$为区间u中比x大的部分的递增序列长度,则分两种情况讨论:
1)u的左区间最大值大于x,此时u的递增序列长度中位于右区间中的部分全部包含,因此$qry(x,u)=cnt[u]-cnt[ls]+qry(x,ls)$(注意不是$cnt[rs]+qry(x,rs)$,因为右区间中的部分序列会被左区间挡住)。
2)u的左区间最大值小于等于x,此时u的递增序列长度中位于左区间中的部分全部不包含,因此$qry(x,u)=qry(x,rs)$。
综上,只需要维护每个区间的最大值和递增序列长度,即可在$O(log^2n)$的时间内完成一次修改操作,而查询操作是$O(1)$的,因此总时间复杂度为$O(mlog^2n)$。
再一次体会到了区间分治的威力。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
const int N=1e5+;
int cnt[N<<],n,m;
db mx[N<<];
#define mid ((l+r)>>1)
#define ls (u<<1)
#define rs (u<<1|1)
int qry(db x,int u,int l,int r) {
if(mx[u]<=x)return ;
if(l==r)return cnt[u];
return mx[ls]>x?cnt[u]-cnt[ls]+qry(x,ls,l,mid):qry(x,rs,mid+,r);
}
void pu(int u,int l,int r) {
mx[u]=max(mx[ls],mx[rs]);
cnt[u]=cnt[ls]+qry(mx[ls],rs,mid+,r);
}
void upd(int p,db x,int u=,int l=,int r=n) {
if(l==r) {cnt[u]=,mx[u]=x; return;}
p<=mid?upd(p,x,ls,l,mid):upd(p,x,rs,mid+,r);
pu(u,l,r);
}
int main() {
scanf("%d%d",&n,&m);
while(m--) {
int x,y;
scanf("%d%d",&x,&y);
upd(x,(db)y/x);
printf("%d\n",cnt[]);
}
return ;
}
BZOJ - 2957 (分块/线段树)的更多相关文章
- BZOJ 2141 分块 线段树
思路: a[i] //By SiriusRen #include <cmath> #include <cstdio> #include <cstring> #inc ...
- BZOJ.4184.shallot(线段树分治 线性基)
BZOJ 裸的线段树分治+线性基,就是跑的巨慢_(:з」∠)_ . 不知道他们都写的什么=-= //41652kb 11920ms #include <map> #include < ...
- [BZOJ 4025]二分图(线段树分治+带边权并查集)
[BZOJ 4025]二分图(线段树分治+带边权并查集) 题面 给出一个n个点m条边的图,每条边会在时间s到t出现,问每个时间的图是否为一个二分图 \(n,m,\max(t_i) \leq 10^5\ ...
- bzoj 3585 mex - 线段树 - 分块 - 莫队算法
Description 有一个长度为n的数组{a1,a2,...,an}.m次询问,每次询问一个区间内最小没有出现过的自然数. Input 第一行n,m. 第二行为n个数. 从第三行开始,每行一个询问 ...
- BZOJ5286 HNOI/AHOI2018转盘(分块/线段树)
显然最优走法是先一直停在初始位置然后一次性走完一圈.将序列倍长后,相当于找一个长度为n的区间[l,l+n),使其中ti+l+n-1-i的最大值最小.容易发现ti-i>ti+n-(i+n),所以也 ...
- CDOJ 1157 数列(seq) 分块+线段树
数列(seq) Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.uestc.edu.cn/#/problem/show/1157 Desc ...
- 【BZOJ 3476】 线段树===
59 懒惰的奶牛贝西所在的牧场,散落着 N 堆牧草,其中第 i 堆牧草在 ( Xi,Yi ) 的位置,数量有 Ai 个单位.贝西从家移动到某一堆牧草的时候,只能沿坐标轴朝正北.正东.正西.正南这四个 ...
- BZOJ 4025: 二分图 [线段树CDQ分治 并查集]
4025: 二分图 题意:加入边,删除边,查询当前图是否为二分图 本来想练lct,然后发现了线段树分治的做法,感觉好厉害. lct做法的核心就是维护删除时间的最大生成树 首先口胡一个分块做法,和hno ...
- CDOJ 1292 卿学姐种花 暴力 分块 线段树
卿学姐种花 题目连接: http://acm.uestc.edu.cn/#/problem/show/1292 Description 众所周知,在喵哈哈村,有一个温柔善良的卿学姐. 卿学姐喜欢和她一 ...
随机推荐
- SqlHelper简单实现(通过Expression和反射)5.Lambda表达式解析类
这个ExpressionHelper类,是整个SqlHelper中,最核心的一个类,主要功能就是将Lambda表达式转换为Sql语句.同时这个转换过程比较复杂,所以下面详细讲解一下思路和这个类的作用. ...
- Hbase 布隆过滤器BloomFilter介绍
转载自:http://blog.csdn.net/opensure/article/details/46453681 1.主要功能 提高随机读的性能 2.存储开销 bloom filter的数据存在S ...
- Spring 之定义切面尝试(基于 XML)
有些场景下只能基于 XML 来定义切面. [Spring 之定义切面尝试] 1.XML 下定义切面(首先是要有一个对应的类...显然要比基于注解的麻烦) <?xml version=" ...
- 做为 Apple Store App 独立开发者,你要搞限时促销,为你的应用生成激活码(或者优惠券),使用 Python 如何生成 200 个激活码(或者优惠券)?
import random import string def GenKey(length): chars = string.ascii_letters + string.digits return ...
- MySQL-Last_Errno: 1594
故障现象 :MySQL slave所在机器自动重启,启动MySQL后,查看主从信息如下: Error_code: 1594 mysql> show slave status \G . ro ...
- const修饰的常量 不能被直接修改 但是可以通过指针进行间接修改
大家都知道如下代码中,被const限定的a是不可以被直接修改的 void main() { const int a = 3; a=1; } 在C++中const修饰的常量,不能被直接修改,但是可以通过 ...
- 实验四 Android程序设计 实验报告 20162305李昱兴
实验四 Android程序设计 实验报告 20162305李昱兴 一.Android Studio的安装测试 1.有关该软件 Android Studio,是基于Itellij IDEA的一款流行的I ...
- Oracle数据类型(4)
字符类型: CHAR(size):固定长度字符串,最大长度2000 bytes VARCHAR2(size):可变长度的字符串,最大长度4000 bytes,可做索引的最大长度749 NCHAR(si ...
- 源码编译配置lnmp部署zabbix
环境说明: [root@wcy ~]# cat /etc/redhat-release CentOS release 6.9 (Final) [root@wcy ~]# uname -a Linux ...
- [Bzoj]5343: [Ctsc2018]混合果汁
5343: [Ctsc2018]混合果汁 题目描述 小 R 热衷于做黑暗料理,尤其是混合果汁. 商店里有 \(n\) 种果汁,编号为 \(0,1,\cdots,n-1\) .\(i\) 号果汁的美味度 ...