2957: 楼房重建
来源:互联网 发布:java调用其他类的函数 编辑:程序博客网 时间:2024/06/08 15:20
题目链接
题目大意:数轴上有n座楼,初始高度为0,每次可以改变某栋楼的高度,求每次改变高度之后从原点可以看到几栋楼
题解:记每栋楼楼顶与原点连线的斜率,那么一栋楼可见当且仅当前面所有楼的斜率都小于这栋楼
分块:块内维护特殊的lis,4 1 2 3 5 那么维护的序列就是4 5
块内暴力修改,查询的时候从下一块找到比这一块max大的即可
线段树做法:结点维护ans和mx,ans表示这个区间的答案,mx表示这个区间的最大斜率。
合并区间:对于节点x,ls的答案可以完全加入x的答案,接下来考虑rs
记ls最大值为
若rs最大值小于等于
若大于
若rs左区间mx小于等于
若rs左区间mx大于
右子区间的答案要用右区间答案-左子区间答案,不能直接调用右子区间本身答案,因为其本身答案没有考虑左子区间的约束。
我的收获:强强强
分块
#include <cstdio>#include <cstring>#include <iostream>#include <cmath>#include <algorithm>using namespace std;#define M 100100 #define eps 1e-10 int n,m,blo,num,pos[M]; double a[M]; struct Block{ int tot,l,r; double ele[1010]; void rebuild()//本来TLE了,换成结构体函数就过了…… { double tmp=0;tot=0; for(int i=l;i<=r;i++) if(a[i]>tmp+eps) tmp=a[i],ele[++tot]=a[i]; } int cal(double &x) { int ret=(tot+1)-(upper_bound(ele+1,ele+tot+1,x+eps)-ele); if(ret) x=ele[tot]; return ret; }}b[120];void work(){ int x,y; for(int i=1;i<=m;i++) { scanf("%d%d",&x,&y); a[x]=(double)y/x; b[pos[x]].rebuild(); int ans=0;double tmp=0; for(int j=1;j<=num;j++) ans+=b[j].cal(tmp); printf("%d\n",ans); }}void init(){ cin>>n>>m; blo=sqrt(n*log(n)/log(2)/2);num=n/blo+1; for(int i=1;i<=n;i++) pos[i]=(i-1)/blo+1; for(int i=1;i<=num;i++) b[i].l=(i-1)*blo+1,b[i].r=min(i*blo,n);}int main(){ init(); work(); return 0;}
线段树
#include <cstdio>#include <cstring>#include <iostream>#include <cmath>#include <algorithm>using namespace std;#define M 100005#define ls x<<1#define rs x<<1|1#define lson l,m,x<<1#define rson m+1,r,x<<1|1#define root 1,n,1int n,m,ans[M<<2],tl[M<<2],tr[M<<2];double mx[M<<2];int cal(double k,int x){ int l=tl[x],r=tr[x]; if(l==r) return mx[x]>k;//特判叶子结点 if(mx[ls]<=k) return cal(k,rs); return ans[x]-ans[ls]+cal(k,ls);}void pushup(int x){mx[x]=max(mx[ls],mx[rs]);ans[x]=ans[ls]+cal(mx[ls],rs);}void build(int l,int r,int x){ if(l==r) return ; int m=(l+r)>>1; tl[x]=l,tr[x]=r; build(lson);build(rson);}void updata(int p,double k,int x){ int l=tl[x],r=tr[x]; if(l==r){ans[x]=1;mx[x]=k;return ;} int m=(l+r)>>1; if(p<=m) updata(p,k,ls); else updata(p,k,rs); pushup(x);}void work(){ int x,y; for(int i=1;i<=m;i++) { scanf("%d%d",&x,&y); updata(x,(double)y/x,1); printf("%d\n",ans[1]); }}void init(){ cin>>n>>m; build(root);}int main(){ init(); work(); return 0;}
0 0
- bzoj 2957 楼房重建
- bzoj 2957: 楼房重建
- bzoj-2957 楼房重建
- BZOJ 2957 楼房重建
- bzoj 2957: 楼房重建
- 2957: 楼房重建
- BZOJ 2957: 楼房重建
- 2957: 楼房重建
- BZOJ 2957 楼房重建
- BZOJ 2957 楼房重建 分块
- BZOJ 2957 楼房重建 分块
- BZOJ 2957 楼房重建 (分块)
- bzoj 2957: 楼房重建(分块)
- 楼房重建
- BZOJ - 2957 楼房重建(分块)
- bzoj 2957: 楼房重建(线段树)
- Bzoj 2957: 楼房重建(线段树)
- bzoj 2957 楼房重建 线段树维护
- 单例模式与静态变量的区别
- LeetCode部分题解
- IOC实现之XML元素解析过程(三)
- LNMP的编译安装与xcache、memcached的安装配置
- 【Shiro】SpringMVC Mybatis Shiro RestTemplate的实现客户端无状态验证及访问控制
- 2957: 楼房重建
- 用requestAnimationFrame做轮播
- Java基础知识点总结
- Linux下编译代码错误-warning: deprecated conversion from string constant to 'char*
- 静态库和动态库
- 离心泵安全操作规程
- LeetCode部分题解
- Spring.net 类库目录
- [转发]机器学习资源大全