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

Posted sto324

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了成都磨子桥技工学校 / 数据结构 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);
    
  
View Code

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

技术图片
#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]);
  
View Code

 

 

以上是关于成都磨子桥技工学校 / 数据结构 Challenge 6(楼房重建)的主要内容,如果未能解决你的问题,请参考以下文章

成都市学校安全教育平台2018官方最新版

成都有几家钢管舞学校 成都钢管舞培训

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

我想站在巨人的肩上——记成都之行

python doomsday_fuel solution.py https://github.com/ivanseed/google-foobar-help/blob/master/challeng

java 有没有更好的方法在java中解决这个问题?https://www.reddit.com/r/dailyprogrammer/comments/7hhyin/20171204_challeng