成都磨子桥技工学校 / 数据结构 Challenge 6(楼房重建)

描述

给一个长为N的数列,有M次操作,每次操作是以下两种之一:

(1)修改数列中的一个数

(2)求数列中有多少个数比它前面的数都大

题解

不会就去参考了一下前辈的题解,说是楼房重建的原题,又去参考了楼房重建的题解(滑稽)。

对于本题,建立线段树,区间记录最大值和有多少数比前面的数都大的数的个数sum。

考虑合并区间时第二个信息,如果右区间最大值小于等于左区间最大值,那么直接取左区间信息,应该比较显然右区间的任何一个元素都比左区间最大值小。

不然的话就要把左区间最大值val带入右区间查询,如果现在val>=左区间最大值,那么查询右区间即可;不然进入左区间查询,然后+sum[rt]-sum[ls],为什么可以不查询右区间呢?因为sum已经记录了整个区间的信息,sum[rt]-sum[ls]就是右区间中比前面的数都大的数的个数(对于整个区间),现在val<左区间最大值,所以就是答案。

如果非要查询val应该就要改成左区间最大值。

#include<bits/stdc++.h>
using namespace std;

const int maxn=100005;
int n,m,cnt;
int root,ls[maxn<<1],rs[maxn<<1],sum[maxn<<1];
int h[maxn<<1],a[maxn];

template<class T>inline void read(T &x){
  x=0;int f=0;char ch=getchar();
  while(!isdigit(ch)) {f|=(ch==‘-‘);ch=getchar();}
  while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
  x= f ? -x : x ;
}

int query(int rt,int l,int r,int val){
  if(l==r) return h[rt]>val;
  int mid=(l+r)>>1;
  if(val>=h[ls[rt]]) return query(rs[rt],mid+1,r,val);
  return query(ls[rt],l,mid,val)+sum[rt]-sum[ls[rt]];
}

int update(int rt,int l,int r){
  if(h[ls[rt]]>=h[rs[rt]]) return sum[ls[rt]];
  return sum[ls[rt]]+query(rs[rt],((l+r)>>1)+1,r,h[ls[rt]]);
}

void build(int &rt,int l,int r){
  rt=++cnt;
  if(l==r){
    h[rt]=a[l];
    sum[rt]=1;
    return ;
  }
  int mid=(l+r)>>1;
  build(ls[rt],l,mid);
  build(rs[rt],mid+1,r);
  sum[rt]=update(rt,l,r);
  h[rt]=max(h[ls[rt]],h[rs[rt]]);
}

void modify(int rt,int l,int r,int pos,int val){
  if(l==r){
    h[rt]=val;
    sum[rt]=1;
    return ;
  }
  int mid=(l+r)>>1;
  if(pos<=mid) modify(ls[rt],l,mid,pos,val);
  else modify(rs[rt],mid+1,r,pos,val);
  sum[rt]=update(rt,l,r);
  h[rt]=max(h[ls[rt]],h[rs[rt]]);
}

int main(){
  read(n);read(m);
  for(int i=1;i<=n;i++){
    int x;read(x);
    a[i]=x;
  }
  build(root,1,n);
  for(int i=1;i<=m;i++){
    char op[2];
    scanf("%s",op);
    if(op[0]==‘Q‘) printf("%d\n",sum[1]);
    else {
      int pos,val;
      read(pos);read(val);
      modify(1,1,n,pos,val);
    }
  }
}

对于楼房重建把每个位置的权值弄成斜率即可。

#include<bits/stdc++.h>
using namespace std;

const int maxn=100005;
int n,m,cnt;
int root,ls[maxn<<1],rs[maxn<<1],sum[maxn<<1];
double h[maxn<<1];

template<class T>inline void read(T &x){
  x=0;int f=0;char ch=getchar();
  while(!isdigit(ch)) {f|=(ch==‘-‘);ch=getchar();}
  while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
  x= f ? -x : x ;
}

int query(int rt,int l,int r,double val){
  if(l==r) return h[rt]>val;
  int mid=(l+r)>>1;
  if(val>h[ls[rt]]) return query(rs[rt],mid+1,r,val);
  return query(ls[rt],l,mid,val)+sum[rt]-sum[ls[rt]];
}

int update(int rt,int l,int r){
  if(h[ls[rt]]>=h[rs[rt]]) return sum[ls[rt]];
  return sum[ls[rt]]+query(rs[rt],((l+r)>>1)+1,r,h[ls[rt]]);
}

void build(int &rt,int l,int r){
  rt=++cnt;
  if(l==r) return ;
  int mid=(l+r)>>1;
  build(ls[rt],l,mid);
  build(rs[rt],mid+1,r);
}

void modify(int rt,int l,int r,int pos,double val){
  if(l==r){
    h[rt]=val;
    sum[rt]=1;
    return ;
  }
  int mid=(l+r)>>1;
  if(pos<=mid) modify(ls[rt],l,mid,pos,val);
  else modify(rs[rt],mid+1,r,pos,val);
  sum[rt]=update(rt,l,r);
  h[rt]=max(h[ls[rt]],h[rs[rt]]);
}

int main(){
  read(n);read(m);
  build(root,1,n);
  for(int i=1;i<=m;i++){
    int pos,val;
    read(pos);read(val);
    modify(1,1,n,pos,1.0*val/pos);
    printf("%d\n",sum[1]);
  }
}

原文地址:https://www.cnblogs.com/sto324/p/11380053.html

时间: 2024-10-13 23:24:39

成都磨子桥技工学校 / 数据结构 Challenge 6(楼房重建)的相关文章

[数据结构] 成都磨子桥技工学校 Challenge Series

Challenge 0: 第一次裸写竟然WA了.... Challenge 1: 不想写了.

[数据结构]bzoj2957楼房重建

Description 小A的楼房外有一大片施工工地,工地上有N栋待建的楼房.每天,这片工地上的房子拆了又建.建了又拆.他经常无聊地看着窗外发呆,数自己能够看到多少栋房子. 为了简化问题,我们考虑这些事件发生在一个二维平面上.小A在平面上(0,0)点的位置,第i栋楼房可以用一条连接(i,0)和(i,Hi)的线段表示,其中Hi为第i栋楼房的高度.如果这栋楼房上任何一个高度大于0的点与(0,0)的连线没有与之前的线段相交,那么这栋楼房就被认为是可见的. 施工队的建造总共进行了M天.初始时,所有楼房都

改变技工学校英语教学困境的路径分析

众所周知,大多数技工学校的学生是成绩差,而没有升入高中的初中毕业生. 这些学生在初中时,就是因为学习态度不端正,学习习惯不好造成的成绩不理想, 尤其是英语这一学科. 上了技校,学生和家长的看法就是赶紧学好技术,早点毕业当工人,英语学得好不好无所谓. 英语课上学生无精打采,昏昏欲睡,课堂上的气氛死气沉沉,让技校的教师很尴尬. 这种英语课堂教学的现状根本无法达到现代科技社会提倡的"要培养双高 , 知识多元化的人才 " 的要求 . 我们作为技工学校的英语教师, 该如何适应社会的发展,改革教学

2015年成都-雅安-新都桥自驾游 蓝天、白云、绿草、牦牛

--------------------------------行程安排:--------------------------------------------- 2015年8月6日   D1天     成都----雅安---石棉--得妥乡---泸定---康定 2015年8月7日   D2天     康定  -  新都桥  住宿:新都桥(雅克国际青年旅行舍 ) --------------------------------准备的物品:-----------------------------

成都鼎育软件培训学校是怎么上课的?

我们都知道,学程序开发,做程序员工资非常高,随随便便就是过万的月薪,近年来,只能手机发展迅速,安卓开发人员急缺,那么,没有一点基础的小白如何才能成为一名优秀的程序员呢?我推荐您到鼎育成都java培训机构看看,零基础入学,高薪推荐入职,仅需几个月,就能完成人生华丽蜕变.下面是鼎育成都android培训课程的授课流程. 编程语言基础阶段 Java编程语言强化学习,完全从实战出发,案例式教学帮助实训生不再纸上谈兵阶段目标:提高实训生编写代码和编程调试能力,使实训生具有扎实的编程功底,同时还能帮助实训生

【数据结构与算法】重建二叉树

只能根据前序中序或者中序后序重建二叉树,不可能根据前序和后序重建,因为需要中序去划分左右子树. 代码实现 /** * 源码名称:ConstructBT.java * 日期:2014-09-05 * 程序功能:重建二叉树(前序中序) * 版权:[email protected] * 作者:A2BGeek */ public class ConstructBT { class Node<T> { T mValue; Node<T> mLeft; Node<T> mRight

进行规划数据更新入库时数据结构被破坏,重建空间索引

需要对要素类的属性进行空间索引重建.使用Arctoolbox工具中的add spatial index工具.具体路径为:system toolboxes->datamanagemente tools->indexes->add spatial index,如下图所示: 输入要素类之后点击OK直接创建要素类的空间索引. 作者:warrenjiang 来源:CSDN 原文:https://blog.csdn.net/warrenjiang/article/details/49641585 原

信安提供的阿的境况蔡燕扥是的胜多负少--2

劳动争议案件中诉讼参与人不诚信行为的表现形式多种多样,导致这种现象很重要的一个原因是法律对不诚信诉讼的有效规制不足. 虽然2012年新修订的民事诉讼法对不诚信诉讼行为做出相应规定,但在实践中对诉讼参与人不诚信诉讼的打击力度偏轻,导致不诚信诉讼的违法成本太低,诉讼参与人感受不到法律的威严,对司法缺乏基本的敬畏,没有把不诚信诉讼当成一个不能触碰的高压线. http://d.pcpop.com/diy/Diy10157166.html http://d.pcpop.com/diy/Diy1015717

一个工作13年的SAP开发人员的回忆:电子科技大学2000级新生入学指南

让我们跟着Jerry的文章,一起回到本世纪初那个单纯美好的年代. 2000年9月,Jerry告别了自己的高中时代,进入到自己心目中的电子游戏大学,开始了四年的本科生活.每个新生,都拿到了这样一本薄薄的小册子. 这是目录: 当时还没有清水河校区,只有九里堤校区,我们都简称为"二校区".关于Jerry的九里堤生活,在我另一篇文章没有电脑没有手机没有网络没有爱情--纪念我的电子科技大学九里堤校区大一生活里有专门讲述. 正文第一页是学校概况,可以看到最下部的页脚,还是UEST,因为当时还没有在