• 线段树 区间合并


    poj3667 Hotel

    区间合并入门题,照着代码打的,

    题意:1 a:询问是不是有连续长度为a的空房间,有的话住进最左边
           2 a b:将[a,a+b-1]的房间清空
    思路:记录区间中最长的空房间,开三个数组,msum[rt]表示节点rt内连续的1的个数的最大值,lsum[rt]表示从节点rt左端点开始连续1的个数,rsum[rt]表示从节点rt右端点开始连续1的个数。。
    线段树操作:update:区间替换 query:询问满足条件的最左端点

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<algorithm>
     5 #include<string>
     6 #include<cmath>
     7 #include<map>
     8 #include<queue>
     9 
    10 using namespace std;
    11 
    12 #define mnx 50005
    13 #define Pi acos(-1.0)
    14 #define ull unsigned long long
    15 #define ll long long 
    16 #define inf 0x3f3f3f3f
    17 #define eps 1e-8
    18 #define MP make_pair
    19 #define lson l, m, rt << 1
    20 #define rson m+1, r, rt << 1 | 1
    21 #define mod 2333333
    22 
    23 int msum[mnx<<2], lsum[mnx<<2], rsum[mnx<<2], cover[mnx<<2];
    24 void pushup( int rt, int m ){
    25     lsum[rt] = lsum[rt<<1];
    26     rsum[rt] = rsum[rt<<1|1];
    27     if( lsum[rt] == m - ( m >> 1 ) ) lsum[rt] += lsum[rt<<1|1];
    28     if( rsum[rt] == ( m >> 1 ) ) rsum[rt] += rsum[rt<<1];
    29     msum[rt] = max( lsum[rt<<1|1] + rsum[rt<<1], max( msum[rt<<1], msum[rt<<1|1] ) );
    30 }
    31 void pushdown( int rt, int m ){
    32     if( cover[rt] != -1 ){
    33         cover[rt<<1] = cover[rt<<1|1] = cover[rt];
    34         msum[rt<<1] = lsum[rt<<1] = rsum[rt<<1] = cover[rt] ? 0 : m - ( m >> 1 );
    35         msum[rt<<1|1] = lsum[rt<<1|1] = rsum[rt<<1|1] = cover[rt] ? 0 : m >> 1;
    36         cover[rt] = -1;
    37     }
    38 }
    39 void build( int l, int r, int rt ){
    40     msum[rt] = lsum[rt] = rsum[rt] = r - l + 1;
    41     if( l == r ) return;
    42     int m = ( l + r ) >> 1;
    43     build( lson ); build( rson );
    44 }
    45 void update( int L, int R, int v, int l, int r, int rt ){
    46     if( L <= l && R >= r ){
    47         msum[rt] = rsum[rt] = lsum[rt] = v ? 0 : r - l + 1;
    48         cover[rt] = v;
    49         return ;
    50     }
    51     pushdown( rt, r - l + 1 );
    52     int m = ( l + r ) >> 1;
    53     if( L <= m ) update( L, R, v, lson );
    54     if( R > m ) update( L, R, v, rson );
    55     pushup( rt, r - l + 1 );
    56 }
    57 int query( int v, int l, int r, int rt ){
    58     if( l == r ) return l;
    59     pushdown( rt, r - l + 1 );
    60     int m = ( l + r ) >> 1;
    61     if( msum[rt<<1] >= v ) return query( v, lson );
    62     else if( rsum[rt<<1] + lsum[rt<<1|1] >= v ) return m - rsum[rt<<1] + 1;
    63     else return query( v, rson );
    64 }
    65 int main(){
    66     int n, m;
    67     while( scanf( "%d %d", &n, &m ) != EOF ){
    68         memset( cover, -1, sizeof(cover) );
    69         build( 1, n, 1 );
    70         int op, a, b;
    71         while( m-- ){
    72             scanf( "%d", &op );
    73             if( op == 1 ){
    74                 scanf( "%d", &a );
    75                 if( msum[1] < a ){
    76                     puts( "0" ); continue;
    77                 }
    78                 int ans = query( a, 1, n, 1 );
    79                 printf( "%d
    ", ans );
    80                 update( ans, ans + a - 1, 1, 1, n, 1 );
    81             }
    82             else{
    83                 scanf( "%d %d", &a, &b );
    84                 update( a, a + b - 1, 0, 1, n, 1 );
    85             }
    86         }
    87     }
    88     return 0;
    89 }
    View Code

     hdu 1540 Tunnel Warfare

    在yamiedie的指导下,过题总是那么轻松。。题目意思很简单,有n个村庄,一开始左右相连,D x表示这个村庄被破坏,就不能与左右两个村庄相连,R 表示修复最近一个被破坏的村庄,Q x表示询问和x村庄相连续的村庄有多少个。。

    做法:线段树的区间连续问题。。D x 就是单点更新,跟上一题差不多。。Q x就先查询x有没有被破坏,没有被破坏就查询区间[1, x-1]的右端点的连续个数rsum[],再查询[x+1,n]的左端点的连续个数lsum[],注意 x - 1 > 0 和 x + 1 <= n的条件,不然会跪的。。

      1 #include<iostream>
      2 #include<cstring>
      3 #include<cstdio>
      4 #include<string>
      5 #include<queue>
      6 #include<algorithm>
      7 #include<cmath>
      8 #include<vector>
      9 
     10 using namespace std;
     11 
     12 #define mnx 200050
     13 #define mxn 50050
     14 #define LL long long
     15 #define mod 1000000007
     16 #define inf 0x3f3f3f3f
     17 #define eps 1e-10
     18 #define Pi acos(-1.0)
     19 #define lson l, m, rt << 1
     20 #define rson m + 1, r, rt << 1 | 1
     21 
     22 int lsum[mnx], rsum[mnx], msum[mnx], pre[mxn], n;
     23 bool vis[mxn];
     24 void build( int l, int r, int rt ){
     25     lsum[rt] = rsum[rt] = msum[rt] = r - l + 1;
     26     if( l == r ){
     27         return ;
     28     }
     29     int m = ( l + r ) >> 1;
     30     build( lson );
     31     build( rson );
     32 }
     33 void pushup( int rt, int m ){
     34     lsum[rt] = lsum[rt<<1];
     35     rsum[rt] = rsum[rt<<1|1];
     36     if( lsum[rt<<1] == m - ( m >> 1 ) ) lsum[rt] += lsum[rt<<1|1];
     37     if( rsum[rt<<1|1] == ( m >> 1 ) ) rsum[rt] += rsum[rt<<1];
     38     msum[rt] = max( lsum[rt<<1|1] + rsum[rt<<1], max( msum[rt<<1], msum[rt<<1|1] ) );
     39 }
     40 void update( int ok, int k, int l, int r, int rt ){
     41     if( l == r ){
     42         msum[rt] = lsum[rt] = rsum[rt] = ok ? r - l + 1 : 0;
     43         return ;
     44     }
     45     int m = ( l + r ) >> 1;
     46     if( k <= m ) update( ok, k, lson );
     47     else update( ok, k, rson );
     48     pushup( rt, r - l + 1 );
     49 }
     50 int query1( int L, int R, int l, int r, int rt ){
     51     if( L == l && R == r ){
     52         return rsum[rt];
     53     }
     54     int m = ( l + r ) >> 1;
     55     if( R <= m ) return query1( L, R, lson );
     56     if( L > m ) return query1( L, R, rson );
     57     int ret = query1( m + 1, R, rson );
     58     if( ret == R - m ){
     59         ret += query1( L, m, lson ); 
     60     }
     61     return ret;
     62 }
     63 int query2( int L, int R, int l, int r, int rt ){
     64     if( L == l && R == r ){
     65         return lsum[rt];
     66     }
     67     int m = ( l + r ) >> 1;
     68     if( R <= m ) return query2( L, R, lson );
     69     if( L > m ) return query2( L, R, rson );
     70     int ret = query2( L, m, lson );
     71     if( ret == m - L + 1 ){
     72         ret += query2( m + 1, R, rson ); 
     73     }
     74     return ret;
     75 }
     76 int main(){
     77     int m;
     78     while( scanf( "%d %d", &n, &m ) != EOF ){
     79         build( 1, n, 1 );
     80         memset( vis, 0, sizeof(vis) );
     81         char ch[2]; int k, cnt = 0;
     82         while( m-- ){
     83             scanf( "%s", ch );
     84             if( ch[0] == 'R' ){
     85                 if( cnt == 0 ) continue;
     86                 k = pre[cnt--];
     87                 if( vis[k] ) update( 1, k, 1, n, 1 );
     88                 vis[k] = 0;
     89             }
     90             else if( ch[0] == 'D' ){
     91                 scanf( "%d", &k );
     92                 if( k < 1 || k > n ) continue;
     93                 pre[++cnt] = k;
     94                 if( !vis[k] ) update( 0, k, 1, n, 1 );
     95                 vis[k] = 1;
     96             }
     97             else{
     98                 scanf( "%d", &k );
     99                 int ans = query1( k, k, 1, n, 1 );
    100                 if( ans ){
    101                     if( k > 1 ) ans += query1( 1, k-1, 1, n, 1 );
    102                     if( k < n ) ans += query2( k+1, n, 1, n, 1 );
    103                 } 
    104                 printf( "%d
    ", ans );
    105             }
    106         }
    107     }
    108     return 0;
    109 }
    View Code

     hdu 2871 Memory Control

    题意:有四个指令,New x就是申请一段长度为x的内存空间;Free  x就是找一个包含X的区间,把那个区间释放掉;Get x就是从1到N 第x个区间;Reset 就是把所有的内存释放掉。

    做法:线段树,int lsum[mnx], rsum[mnx], msum[mnx], sum[mnx], tot[mnx], L[mnx], R[mnx], cover[mnx], cnt。。先解释一下各个数组的含义,msum[rt]表示节点rt内连续的可用空间的长度的最大值,lsum[rt]表示从节点rt左端点开始连续可用空间的长度,rsum[rt]表示从节点rt右端点开始连续可用空间的长度;cover[rt] 表示这个区间有没有被用,-1就是最初没有使用的状态,1表示这个区间全都用了,0表示这个区间已经释放掉了;sum[rt]用来记录这是第cnt个被用的区间,sum[rt]=0表示这个区间没有被用,L[cnt]和R[cnt]表示第cnt个被用的区间的左端点和右端点是多少,这3个数组用来辅助Free操作;tot[]就是用来辅助Get操作,表示当前有多少个区间被用了,每用一个区间,就在该区间的左端点的tot[]上加上1,每释放一个区间,就在释放的区间的左端点减去1。。

    对于Reset操作,不能重建线段树,这样会超时,只需要从 (1, n)成段更新,利用懒惰标记向下更新。。update函数就是用来更新 要用的区间或者要释放的区间,update1就是用来更新 左端点 tot[]的值,query函数就是在New x的时候,查找可用内存的左端点,find函数就是在Free x的时候查找 x的cnt值, findtot就是在Get x的时候查找 第x个被用的区间的左端点

      1 #include<iostream>
      2 #include<cstring>
      3 #include<cstdio>
      4 #include<string>
      5 #include<queue>
      6 #include<algorithm>
      7 #include<cmath>
      8 #include<vector>
      9 
     10 using namespace std;
     11 
     12 #define mnx 200050
     13 #define mxn 50050
     14 #define LL long long
     15 #define mod 1000000007
     16 #define inf 0x3f3f3f3f
     17 #define eps 1e-10
     18 #define Pi acos(-1.0)
     19 #define lson l, m, rt << 1
     20 #define rson m + 1, r, rt << 1 | 1
     21 
     22 int lsum[mnx], rsum[mnx], msum[mnx], sum[mnx], tot[mnx], L[mnx], R[mnx], cover[mnx], cnt;
     23 void build( int l, int r, int rt ){
     24     lsum[rt] = rsum[rt] = msum[rt] = r - l + 1;
     25     cover[rt] = -1, sum[rt] = 0, tot[rt] = 0;
     26     if( l == r ) return;
     27     int m = ( l + r ) >> 1;
     28     build( lson );
     29     build( rson );
     30 }
     31 void pushup( int rt, int m ){
     32     tot[rt] = tot[rt<<1] + tot[rt<<1|1];
     33     lsum[rt] = lsum[rt<<1];
     34     rsum[rt] = rsum[rt<<1|1];
     35     if( lsum[rt<<1] == ( m - ( m >> 1 ) ) ) lsum[rt] += lsum[rt<<1|1];
     36     if( rsum[rt<<1|1] == ( m >> 1 ) ) rsum[rt] += rsum[rt<<1];
     37     msum[rt] = max( rsum[rt<<1] + lsum[rt<<1|1], max( msum[rt<<1], msum[rt<<1|1] ) );
     38 }
     39 void pushdown( int rt, int m ){
     40     if( cover[rt] != -1 ){
     41         cover[rt<<1] = cover[rt<<1|1] = cover[rt];
     42         msum[rt<<1] = lsum[rt<<1] = rsum[rt<<1] = cover[rt] ? 0 : m - ( m >> 1 );
     43         msum[rt<<1|1] = lsum[rt<<1|1] = rsum[rt<<1|1] = cover[rt] ? 0 : ( m >> 1 );
     44         if( cover[rt] ){
     45             sum[rt<<1] = sum[rt<<1|1] = sum[rt];
     46         }
     47         else sum[rt<<1] = sum[rt<<1|1] = 0;
     48         if( tot[rt] == 0 ) tot[rt<<1] = tot[rt<<1|1] = tot[rt];
     49         cover[rt] = -1;
     50     }
     51 }
     52 void update( int L, int R, int v, int l, int r, int rt ){
     53     if( L <= l && R >= r ){
     54         lsum[rt] = rsum[rt] = msum[rt] = v ? 0 : r - l + 1;
     55         sum[rt] = v ? cnt : 0; cover[rt] = v;
     56         return;
     57     }
     58     pushdown( rt, r - l + 1 );
     59     int m = ( l + r ) >> 1;
     60     if( L <= m ) update( L, R, v, lson );
     61     if( R > m ) update( L, R, v, rson );
     62     pushup( rt, r -l + 1 );
     63 }
     64 void update1( int k, int v, int l, int r, int rt ){
     65     if( l == r ){
     66         tot[rt] = v;
     67         return ;
     68     }
     69     pushdown( rt, r - l + 1 );
     70     int m = ( l + r ) >> 1;
     71     if( k <= m ) update1( k, v, lson );
     72     else update1( k, v, rson );
     73     pushup( rt, r - l + 1 );
     74 }
     75 int query( int k, int l, int r, int rt ){
     76     if( l == r ) return l;
     77     pushdown( rt, r - l + 1 );
     78     int m = ( l + r ) >> 1, ret;
     79     if( msum[rt<<1] >= k ) ret = query( k, lson );
     80     else if( rsum[rt<<1] + lsum[rt<<1|1] >= k ){
     81         ret = m - rsum[rt<<1] + 1;
     82     }
     83     else ret = query( k, rson );
     84     pushup( rt, r -l + 1 );
     85     return ret;
     86 }
     87 int find( int k, int l, int r, int rt ){
     88     if( l == r ){
     89         return sum[rt];
     90     }
     91     pushdown( rt, r - l + 1 );
     92     int m = ( l + r ) >> 1, ret;
     93     if( k <= m ) ret = find( k, lson );
     94     else ret = find( k, rson );
     95     pushup( rt, r - l + 1 );
     96     return ret;
     97 }
     98 int findtot( int k, int l, int r, int rt ){
     99     if( l == r ){
    100         return l;
    101     }
    102     pushdown( rt, r - l + 1 );
    103     int m = ( l + r ) >> 1, ret;
    104     if( tot[rt<<1] >= k ) ret = findtot( k, lson );
    105     else ret = findtot( k - tot[rt<<1], rson );
    106     pushup( rt, r -l + 1 );
    107     return ret;
    108 }
    109 int main(){
    110     int n, m, flag = 0;
    111     //freopen( "in.txt", "w", stdout );
    112     while( scanf( "%d %d", &n, &m ) != EOF ){
    113         cnt = 0;
    114         build( 1, n, 1 );
    115         char ch[50]; int k;
    116         while( m-- ){
    117             scanf( "%s", ch );
    118             if( ch[0] == 'R' ){
    119                 puts( "Reset Now" );
    120                 update( 1, n, 0, 1, n, 1 );
    121                 tot[1] = 0;
    122                 cnt = 0;
    123             }
    124             else if( ch[0] == 'N' ){
    125                 scanf( "%d", &k );
    126                 if( msum[1] < k || k <= 0 || k > n ){
    127                     puts( "Reject New" );continue;
    128                 }
    129                 ++cnt;
    130                 int ans = query( k, 1, n, 1 );
    131                 L[cnt] = ans, R[cnt] = ans + k - 1;
    132                 printf( "New at %d
    ", ans );
    133                 update( ans, ans + k - 1, 1, 1, n, 1 );
    134                 update1( ans, 1, 1, n, 1 );
    135             }
    136             else if( ch[0] == 'F' ){
    137                 scanf( "%d", &k );
    138                 int ans = find( k, 1, n, 1 );
    139                 if( ans <= 0 || k <= 0 || k > n ){
    140                     puts( "Reject Free" ); continue;
    141                 }
    142                 printf( "Free from %d to %d
    ", L[ans], R[ans] );
    143                 update( L[ans], R[ans], 0, 1, n, 1 );
    144                 update1( L[ans], 0, 1, n, 1 );
    145             }
    146             else{
    147                 scanf( "%d", &k );
    148                 if( tot[1] < k || k <= 0 ){
    149                     puts( "Reject Get" ); continue;
    150                 }
    151                 int ans = findtot( k, 1, n, 1 );
    152                 printf( "Get at %d
    ", ans );
    153             }
    154         }
    155         cout<<endl;
    156     }
    157     return 0;
    158 }
    View Code
  • 相关阅读:
    Powershell分支条件
    Powershell基础
    初识PowerShell
    设计模式--策略模式
    设计模式--简单工程模式
    StandardWrapper
    Tomcat的安全性
    算法效率 简单的增长率 参照

    排序算法之 归并排序
  • 原文地址:https://www.cnblogs.com/LJ-blog/p/3917104.html
Copyright © 2020-2023  润新知