zoukankan      html  css  js  c++  java
  • UVALive

    题目链接

    题意:在一条直线上依次建造n座建筑物,每座建筑物建造完成后询问它在多长的部分是最高的。

    比较好想的方法是用线段树分别维护每个区间的最小值mi和最大值mx,当建造一座高度为x的建筑物时,若mi>x则答案无贡献,直接退出,若mx<=x则区间赋值为x,答案加上区间长度。其他情况需要继续递归搜索。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int N=1e5+10,inf=0x3f3f3f3f;
     5 int n,mx[N<<2],mi[N<<2],lz[N<<2];
     6 ll ans;
     7 #define ls (u<<1)
     8 #define rs (u<<1|1)
     9 #define mid ((l+r)>>1)
    10 void pu(int u) {mx[u]=max(mx[ls],mx[rs]),mi[u]=min(mi[ls],mi[rs]);}
    11 void change(int u,int x) {mx[u]=mi[u]=lz[u]=x;}
    12 void pd(int u) {if(~lz[u])change(ls,lz[u]),change(rs,lz[u]),lz[u]=-1;}
    13 void build(int u=1,int l=1,int r=100000) {
    14     lz[u]=-1;
    15     if(l==r) {mx[u]=mi[u]=0; return;}
    16     build(ls,l,mid),build(rs,mid+1,r),pu(u);
    17 }
    18 void upd(int L,int R,int x,int u=1,int l=1,int r=100000) {
    19     if(l>R||r<L||x<mi[u])return;
    20     if(l>=L&&r<=R&&x>=mx[u]) {ans+=r-l+1,change(u,x); return;}
    21     pd(u),upd(L,R,x,ls,l,mid),upd(L,R,x,rs,mid+1,r),pu(u);
    22 }
    23 int main() {
    24     int T;
    25     for(scanf("%d",&T); T--;) {
    26         build(),ans=0;
    27         scanf("%d",&n);
    28         while(n--) {
    29             int l,r,x;
    30             scanf("%d%d%d",&l,&r,&x),r--;
    31             upd(l,r,x);
    32         }
    33         printf("%lld
    ",ans);
    34         scanf(" 0");
    35     }
    36     return 0;
    37 }

    这种方法对于随机数据是比较快的,但会被一些极端的数据卡成n^2,比如先来个[1,2,100000],[3,4,100000],...(每两个位置建一座很高的建筑物),然后来一堆[1,100000,1],[1,100000,2],...,遇到这种情况就GG了。

    解决方法是改成吉司机线段树(Segment tree beats),稳定nlogn~

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int N=1e5+10,inf=0x3f3f3f3f;
     5 int n,mi[N<<2],se[N<<2],nmi[N<<2],lz[N<<2];
     6 ll ans;
     7 #define ls (u<<1)
     8 #define rs (u<<1|1)
     9 #define mid ((l+r)>>1)
    10 void pu(int u) {
    11     mi[u]=min(mi[ls],mi[rs]),se[u]=max(mi[ls],mi[rs]);
    12     se[u]=se[u]==mi[u]?min(se[ls],se[rs]):min(se[u],min(se[ls],se[rs]));
    13     nmi[u]=(mi[ls]==mi[u]?nmi[ls]:0)+(mi[rs]==mi[u]?nmi[rs]:0);
    14 }
    15 void change(int u,int x) {mi[u]=lz[u]=x;}
    16 void pd(int u) {
    17     if(~lz[u]) {
    18         if(mi[ls]<lz[u])change(ls,lz[u]);
    19         if(mi[rs]<lz[u])change(rs,lz[u]);
    20         lz[u]=-1;
    21     }
    22 }
    23 void build(int u=1,int l=1,int r=100000) {
    24     lz[u]=-1;
    25     if(l==r) {mi[u]=0,se[u]=inf,nmi[u]=1; return;}
    26     build(ls,l,mid),build(rs,mid+1,r),pu(u);
    27 }
    28 void upd(int L,int R,int x,int u=1,int l=1,int r=100000) {
    29     if(l>R||r<L||mi[u]>x)return;
    30     if(l>=L&&r<=R&&se[u]>x) {change(u,x),ans+=nmi[u]; return;}
    31     pd(u),upd(L,R,x,ls,l,mid),upd(L,R,x,rs,mid+1,r),pu(u);
    32 }
    33 int main() {
    34     int T;
    35     for(scanf("%d",&T); T--;) {
    36         build(),ans=0;
    37         scanf("%d",&n);
    38         while(n--) {
    39             int l,r,x;
    40             scanf("%d%d%d",&l,&r,&x),r--;
    41             upd(l,r,x);
    42         }
    43         scanf(" 0");
    44         printf("%lld
    ",ans);
    45     }
    46     return 0;
    47 }
  • 相关阅读:
    linux ls
    ExtJs 弹出窗口
    Redhat5 装中文
    Linux下配置JDK以及报cannot restore segment prot after reloc: Permission denied错解决方案
    工具
    得到剪切的图片
    label button等设置不同颜色的标题
    UITableView UITextField 键盘挡住
    给出颜色生成图片
    一个不错的学习网站
  • 原文地址:https://www.cnblogs.com/asdfsag/p/10775169.html
Copyright © 2011-2022 走看看