zoukankan      html  css  js  c++  java
  • 可持续化线段树(例题Sign on Fence[Codeforces 484E])

    刚刚学习的想记录一下:

    第一次接触可持续化线段树,很懵。。。

    题目:

    题目描述

    izon the Champion has recently finished painting his wood fence. The fence consists of a sequence of n panels of 1 meter width and of arbitrary height. The i-th panel's height is 

    hi meters. The adjacent planks follow without a gap between them.

    After Bizon painted the fence he decided to put a "for sale" sign on it.The sign will be drawn on a rectangular

    piece of paper and placed on the fence so that the sides of the sign are parallel to the fence panels and are

    also aligned with the edges of some panels. Bizon the Champion introduced the following constraints for the sign position:

      1 The width of the sign should be exactly w meters.

      2 The sign must fit into the segment of the fence from the l-th to the r-th panels, inclusive

       (also, it can't exceed the fence's bound in vertical direction).

    The sign will be really pretty, So Bizon the Champion wants the sign's height to be as large as possible.

    You are given the description of the fence and several queries for placing sign. For each query print the maximum

    possible height of the sign that can be placed on the corresponding segment of the fence with the given fixed width of the sign.

    输入

    The first line of the input contains integer n — the number of panels in the fence (1 ≤ n ≤ 105).

    The second line contains n space-separated integers hi, — the heights of the panels (1 ≤ hi ≤ 109).

    The third line contains an integer m — the number of the queries (1 ≤ m ≤ 105).

    The next m lines contain the descriptions of the queries,

    each query is represented by three integers lr and w (1 ≤ l ≤ r ≤ n,1 ≤ w ≤ r - l + 1) 

    — the segment of the fence and the width of the sign respectively.

    输出

    For each query print the answer on a separate line — the maximum height of the sign that can be put in the corresponding segment of the fence with all the conditions being satisfied.

    样例输入

    5 1 2 2 3 3 3 2 5 3 2 5 2 1 5 5

    样例输出

    2 3 1
     
     
    好吧大意就是给我们一组数,并给出m个询问,每个询问包括l,r,w三个数,询问我们在l到r这个区间内连续取W个数,使这w个数中的最小值尽可能的大,输出这个最大的最小值。
    首先我们先假设在当前的询问下X这个数可以成为连续w个数中的最小值(x一定为某个数的值),然后把数列中大于X的数标为1小于X的数标为0,那么如果我们求出这个01串中最长的1串的长度为s,且s>=w的话,x就可以拿去更新当前答案,然后我们就枚举比x大的值看是否符合条件,当然这个枚举过程用二分实现。
    用线段树求一串数中最长的1串,应该都做过。所以问题就变成了我们如何来建立这个01串,很显然,我们不可能去构造n棵线段树。假设有两个数x,y且x>y那么很显然y的01串是的01串的基础上多添加了几个1,所以我们可以用可持续化线段树来维护当前01串下的最长1串的长度。
    下面是程序:
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    struct ding{
      int h,node;
    }a[100009];
    struct ding2{
      int l,r,mx,ls,rs,lx,rx;
    }f[2000000];
    int num,root[100009],n,m;
    bool cmp(ding x,ding y){return (x.h==y.h?x.node>y.node:x.h>y.h);}
    void build(int& roo,int lef,int righ)
    {
      if (roo==0) roo=++num;
      f[roo].l=lef;f[roo].r=righ;
      if (lef==righ) return;
      int mid=(lef+righ)/2;
      build(f[roo].ls,lef,mid); build(f[roo].rs,mid+1,righ);
    }
    void update(int x)
    {
      int lson=f[x].ls,rson=f[x].rs;
      f[x].lx=f[lson].r-f[lson].l+1==f[lson].mx?f[lson].lx+f[rson].lx:f[lson].lx;
      f[x].rx=f[rson].r-f[rson].l+1==f[rson].mx?f[rson].rx+f[lson].rx:f[rson].rx;
      f[x].mx=max(max(f[lson].mx,f[rson].mx),f[lson].rx+f[rson].lx);
    }
    int insert(int las,int w)
    {
      int now=++num;
      f[now]=f[las];
      if ((f[now].l==w)&&(f[now].r==w)){f[now].mx=f[now].lx=f[now].rx=1;return now;}
      int mid=(f[now].l+f[now].r)/2;
      if (w<=mid) f[now].ls=insert(f[las].ls,w);
      else f[now].rs=insert(f[las].rs,w);
      update(now);
      return now;
    }
    ding2 query(int now,int lef,int righ)
    {
      if ((lef<=f[now].l)&&(f[now].r<=righ)) return f[now];
      int mid=(f[now].l+f[now].r)/2;
      if (righ<=mid) return query(f[now].ls,lef,righ);
      else if (lef>mid) return query(f[now].rs,lef,righ);
      else
      {
          ding2 t1=query(f[now].ls,lef,righ),t2=query(f[now].rs,lef,righ),t3;
          t3.l=t1.l; t3.r=t2.r;
          t3.mx=max(t1.rx+t2.lx,max(t1.mx,t2.mx));
          t3.lx=t1.mx==t1.r-t1.l+1?t1.mx+t2.lx:t1.lx;
          t3.rx=t2.mx==t2.r-t2.l+1?t2.mx+t1.rx:t2.rx;
          return t3;
      }
    }
    int main()
    {
      scanf("%d",&n);
      for (int i=1;i<=n;i++) 
      {
        scanf("%d",&a[i].h);
        a[i].node=i;
      }
      sort(a+1,a+1+n,cmp);
      num=1;
      build(root[0],1,n);
      for (int i=1;i<=n;i++) root[i]=insert(root[i-1],a[i].node);
      scanf("%d",&m);
      for (int i=1;i<=m;i++)
      {
        int pl,pr,w;
          scanf("%d%d%d",&pl,&pr,&w);
          int nl=1,nr=n;
          while (nl<nr)
          {
            int mid=(nl+nr)/2;
          if (query(root[mid],pl,pr).mx>=w) nr=mid;    
          else nl=mid+1;
        }
        printf("%d
    ",a[nr].h);
      }
      return 0;
    }
     
  • 相关阅读:
    BZOJ_3589_动态树_容斥原理+树链剖分
    吴裕雄--天生自然ORACLE数据库学习笔记:SQL语言基础
    吴裕雄--天生自然ORACLE数据库学习笔记:常用SQL*Plus命令
    吴裕雄--天生自然python数据清洗与数据可视化:MYSQL、MongoDB数据库连接与查询、爬取天猫连衣裙数据保存到MongoDB
    吴裕雄--天生自然PYTHON爬虫:使用Selenium爬取大型电商网站数据
    吴裕雄--天生自然PYTHON爬虫:使用Scrapy抓取股票行情
    吴裕雄--天生自然PYTHON爬虫:爬取某一大型电商网站的商品数据(效率优化以及代码容错处理)
    吴裕雄--天生自然PYTHON爬虫:爬取某一大型电商网站的商品数据(优化)
    吴裕雄--天生自然神经网络与深度学习实战Python+Keras+TensorFlow:从零开始实现识别手写数字的神经网络
    吴裕雄--天生自然神经网络与深度学习实战Python+Keras+TensorFlow:神经网络的理论基础
  • 原文地址:https://www.cnblogs.com/2014nhc/p/7141489.html
Copyright © 2011-2022 走看看