• 线段树专辑——pku 3667 Hotel


    http://poj.org/problem?id=3667

    哈哈,经典中的经典题啊。利用线段树求最大连续空闲区间,并返回空闲区间的起点坐标。

    View Code
      1 #include<iostream>
    2 #include<string>
    3 #include<algorithm>
    4 using namespace std;
    5
    6 struct node
    7 {
    8 int l;
    9 int r;
    10 int l_val; //从左节点数起的最大连续空闲区间
    11 int r_val; //从右节点起的最大连续空闲区间
    12 int max_val; //整个区间的最大连续空闲区间
    13 int cover; //当前区间的占用情况,1表示占用,0表示不占用,-1表示既有占用又有不占用
    14 };
    15
    16 node tree[250000];
    17 int n,m;
    18
    19 int max(int a,int b)
    20 {
    21 return a>b?a:b;
    22 }
    23
    24 void build(int i,int l,int r)
    25 {
    26 tree[i].l=l;
    27 tree[i].r=r;
    28 tree[i].cover=0;
    29 tree[i].l_val=tree[i].r_val=tree[i].max_val=r-l+1; //开始所有区间都未使用
    30 if(l==r)
    31 return;
    32 int mid=(l+r)/2;
    33 build(2*i,l,mid);
    34 build(2*i+1,mid+1,r);
    35 }
    36
    37 void fun(int i) //跟新区间
    38 {
    39 if(tree[i].cover==0)
    40 {
    41 tree[i].l_val=tree[i].r_val=tree[i].max_val=tree[i].r-tree[i].l+1;
    42 }
    43 else if(tree[i].cover==1)
    44 {
    45 tree[i].l_val=tree[i].r_val=tree[i].max_val=0;
    46 }
    47 }
    48
    49 void updata(int i,int l,int r,int w)
    50 {
    51 if(tree[i].l>r || tree[i].r<l)
    52 return;
    53 if(tree[i].l>=l && tree[i].r<=r)
    54 {
    55 tree[i].cover=w; //跟新该段情况
    56 fun(i); //并根据cover跟新其他域
    57 return;
    58 }
    59 if(tree[i].cover!=-1)
    60 {
    61 tree[2*i].cover=tree[2*i+1].cover=tree[i].cover;
    62 fun(2*i); fun(2*i+1);
    63 tree[i].cover=-1;
    64 }
    65 updata(2*i,l,r,w);
    66 updata(2*i+1,l,r,w);
    67 if(tree[2*i].cover==tree[2*i+1].cover) //由下而上跟新所有信息
    68 tree[i].cover=tree[2*i].cover;
    69 else
    70 tree[i].cover=-1;
    71 tree[i].l_val=tree[2*i].l_val+(tree[2*i].cover==0 ? tree[2*i+1].l_val:0);
    72 tree[i].r_val=tree[2*i+1].r_val+(tree[2*i+1].cover==0 ? tree[2*i].r_val:0);
    73 tree[i].max_val=max(max(tree[2*i].max_val,tree[2*i+1].max_val),(tree[2*i].r_val+tree[2*i+1].l_val));
    74 }
    75
    76 int find(int i,int w)
    77 {
    78 if(tree[i].cover==0 && tree[i].l_val>=w) //从左边起能找到
    79 {
    80 return tree[i].l;
    81 }
    82 if(tree[i].cover==1)
    83 {
    84 return 0;
    85 }
    86 if(tree[i].cover==-1 && tree[i].max_val>=w)
    87 {
    88 if(tree[2*i].max_val>=w) //左边还有足够空间,向左递归
    89 return find(2*i,w);
    90 else if(tree[2*i].r_val+tree[2*i+1].l_val>=w) //如果中间有足够空间,直接计算
    91 {
    92 return tree[2*i].r-tree[2*i].r_val+1;
    93 }
    94 else
    95 return find(2*i+1,w); //向右递归
    96 }
    97 return 0;
    98 }
    99
    100 int main()
    101 {
    102 freopen("D:\\in.txt","r",stdin);
    103 int i,a,b,c;
    104 while(scanf("%d%d",&n,&m)!=EOF)
    105 {
    106 build(1,1,n);
    107 for(i=0;i<m;i++)
    108 {
    109 scanf("%d",&c);
    110 if(c==1)
    111 {
    112 scanf("%d",&a);
    113 b=find(1,a);
    114 printf("%d\n",b);
    115 if(b)
    116 {
    117 updata(1,b,b+a-1,1);
    118 }
    119 }
    120 else
    121 {
    122 scanf("%d%d",&a,&b);
    123 updata(1,a,a+b-1,0);
    124 }
    125 }
    126 }
    127 return 0;
    128 }
  • 相关阅读:
    非旋Treap——fhq treap
    LCA
    树链剖分
    复习计划
    BZOJ2565: 最长双回文串(回文树)
    回文自动机
    luogu P3796 【模板】AC自动机(加强版)
    【BZOJ2908】 又是nand
    【HDU2460】 Network
    【CF786B】 Legacy
  • 原文地址:https://www.cnblogs.com/ka200812/p/2244966.html
Copyright © 2020-2023  润新知