zoukankan      html  css  js  c++  java
  • 【HDU 2871 Memory Control】线段树之区间操作

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2871

    题目大意:

     四个操作:

    1、New x     找一段长为x的空区间段填满。  下面用0表示空单元,1表示非空单元。

    2、Free x  释放包含x的区间段

    3、 Get x 找到第x个区间段

    4、将整个区间都置为空。

    解题思路:

         可以说这题应该算是线段树之区间操作里面比较好的经典题了。要注意的地方很多。对vector容器的用法又了解了很多。赞一个

    View Code
      1 #include <cstdio>
      2 #include <vector>
      3 #include <iostream>
      4 using namespace std;
      5 
      6 #define  lz  2*u,l,mid
      7 #define  rz  2*u+1,mid+1,r
      8 const int maxn=50005;
      9 int flag[4*maxn];
     10 
     11 struct segment
     12 {
     13     int lm; // 从区间左端点开始的连续0个数;
     14     int rm; // 以区间右端点结束的连续0个数;
     15     int sm; // 整个区间最长连续的0个数;
     16 } tree[4*maxn];
     17 
     18 struct node
     19 {
     20     int s, d;
     21 };
     22 node tmp;
     23 vector<node>vt;
     24 
     25 void push_up(int u, int l, int r)
     26 {
     27     int mid= (l+r)>>1;
     28     tree[u].lm= tree[u*2].lm;
     29     tree[u].rm= tree[u*2+1].rm;
     30     tree[u].sm= max( tree[u*2].sm, tree[u*2+1].sm );
     31     if( tree[u*2].lm == mid-l+1 ) tree[u].lm += tree[u*2+1].lm;
     32     if( tree[u*2+1].rm == r-mid ) tree[u].rm += tree[u*2].rm;
     33     int t= tree[u*2].rm + tree[u*2+1].lm;
     34     if( t > tree[u].sm )  tree[u].sm= t;
     35 }
     36 
     37 void push_down(int u, int l, int r)
     38 {
     39     if(flag[u]>=0)
     40     {
     41         int mid=(l+r)>>1;
     42         flag[2*u]=flag[2*u+1]=flag[u];
     43         tree[2*u].lm= tree[2*u].rm= tree[2*u].sm= flag[u]?0:mid-l+1;
     44         tree[2*u+1].lm= tree[2*u+1].rm= tree[2*u+1].sm= flag[u]?0:r-mid;
     45         flag[u]=-1;
     46     }
     47 }
     48 
     49 void build(int u, int l, int r)
     50 {
     51     flag[u]=-1;
     52     if(l==r)
     53     {
     54         tree[u].lm= tree[u].rm= tree[u].sm= 1;
     55         return;
     56     }
     57     int mid= (l+r)>>1;
     58     build(lz);
     59     build(rz);
     60     push_up(u, l, r);
     61 }
     62 
     63 void Update(int u, int l, int r, int tl, int tr, int c)
     64 {
     65     if(tl<=l&&r<=tr)
     66     {
     67         tree[u].lm=tree[u].rm=tree[u].sm=c?0:r-l+1;
     68         flag[u]=c;
     69         return ;
     70     }
     71     push_down(u,l,r);
     72     int mid=(l+r)>>1;
     73     if(tr<=mid) Update(lz,tl,tr,c);
     74     else if(tl>mid) Update(rz,tl,tr,c);
     75     else
     76     {
     77         Update(lz,tl,mid,c);
     78         Update(rz,mid+1,tr,c);
     79     }
     80     push_up(u,l,r);
     81 }
     82 
     83 int  Query(int u, int l, int r, int p)
     84 {
     85     if(tree[u].sm==p&&r-l+1==p)   ///不仅要tree[u].sm==p而且要整个区间都被0覆盖,否则会出错
     86     {
     87         return l;
     88     }
     89     push_down(u,l,r);
     90     int mid= (l+r)>>1, t;
     91     if(p<=tree[2*u].sm)  return Query(lz,p);
     92     else if(tree[2*u].rm+tree[2*u+1].lm>=p) return mid-tree[2*u].rm+1;
     93     else return Query(rz,p);
     94 }
     95 
     96 int find(int tp)    ///二分查找
     97 {
     98     int l=0, r=vt.size()-1, mid, ans=-1;
     99     while(l<=r)
    100     {
    101         int mid=(l+r)>>1;
    102         if(vt[mid].s<=tp)
    103         {
    104             ans=mid;
    105             l=mid+1;
    106         }
    107         else r=mid-1;
    108     }
    109     return ans;
    110 }
    111 
    112 int main()
    113 {
    114     int n, m;
    115     while(cin >> n >> m)
    116     {
    117         build(1,1,n);
    118         vt.clear();
    119         while(m--)
    120         {
    121             char ch[6];
    122             scanf("%s",ch);
    123             if(ch[0]=='R')
    124             {
    125                 vt.clear();
    126                 Update(1,1,n,1,n,0);
    127                 puts("Reset Now");
    128                 continue;
    129             }
    130             int op;
    131             scanf("%d",&op);
    132             if(ch[0]=='N')
    133             {
    134                 if(tree[1].sm>=op)
    135                 {
    136                     int st=Query(1,1,n,op);
    137                     tmp.s=st, tmp.d=st+op-1;
    138                     int id=find(tmp.s);
    139                     vt.insert(vt.begin()+id+1,tmp);
    140                     printf("New at %d\n",tmp.s);
    141                     Update(1,1,n,tmp.s,tmp.d,1);  ///!!!这里注意了,查询完了还要进行相应的更新
    142                 }
    143                 else
    144                     puts("Reject New");
    145             }
    146             else if(ch[0]=='G')
    147             {
    148                 if(vt.size()>=op)
    149                     printf("Get at %d\n",vt[op-1].s);
    150                 else puts("Reject Get");
    151             }
    152             else if(ch[0]=='F')
    153             {
    154                 int id=find(op);
    155                 if(id==-1||vt[id].d<op) puts("Reject Free");
    156                 else
    157                 {
    158                     Update(1,1,n,vt[id].s,vt[id].d,0);
    159                     printf("Free from %d to %d\n",vt[id].s,vt[id].d);
    160                     vt.erase(vt.begin()+id,vt.begin()+id+1); ///删除区间[s,d)内的元素,左闭右开
    161                 }
    162             }
    163         }
    164         puts("");
    165     }
    166     return 0;
    167 }
  • 相关阅读:
    [TJOI2013]循环格
    [CQOI2017]小Q的表格
    【51nod 1514】 美妙的序列
    【bzoj3456】 城市规划
    [SHOI2010]最小生成树
    CF438E The Child and Binary Tree
    bzoj 4712: 洪水
    POJ-3069 Saruman's Army---区间选点
    POJ-3617 Best Cow Line---字符串贪心
    HDU-1850 Being a Good Boy in Spring Festival---尼姆博奕的运用
  • 原文地址:https://www.cnblogs.com/kane0526/p/2941652.html
Copyright © 2011-2022 走看看