zoukankan      html  css  js  c++  java
  • hdu--3275--线段树<again>

    又加强了 对线段树 延迟标记的理解~~

    题意很简单 给你一串数字01组成. 每次必须操作K个数 将其翻转 即0->1   1->0 就相当 对于一段区间 [ L , L+K-1 ] 的0和1的数量 进行swap操作

    首先 解这题 一点必须想到 求最少操作次数 肯定是从最左边开始.

    那么我每次 query(find)操作 查找到最左边的0的位置 如果不存在就返回-1 表示 全是1了

    然后对这个[ pos , pos+k-1 ]进行翻转操作 这边有个判断 就是如果 pos+k-1 > n的话 就相当于无法成功通过翻转实现全部1的结果了

    注意下 pushDown  和 pushUp函数的使用及函数体内容....  这些都是 精华啊 值得去理解~ 而且我也讲不明白..

      1 //0代表灯笼是暗的    1代表灯笼是亮的
      2 #include <iostream>
      3 #include <algorithm>
      4 using namespace std;
      5 
      6 const int size =  100010;
      7 char str[size];
      8 struct data
      9 {
     10     int L;
     11     int R;
     12     int flag;
     13     int numOne , numZero;
     14 }tree[size*4];
     15 
     16 void pushUp( int root )
     17 {
     18     tree[root].numOne = tree[root<<1].numOne + tree[root<<1|1].numOne;
     19     tree[root].numZero = tree[root<<1].numZero + tree[root<<1|1].numZero;
     20 }
     21 
     22 void pushDown( int root )
     23 {
     24     tree[root<<1].flag ^= 1;
     25     tree[root<<1|1].flag ^= 1;
     26     swap( tree[root<<1].numZero , tree[root<<1].numOne );
     27     swap( tree[root<<1|1].numZero , tree[root<<1|1].numOne );
     28 }
     29 
     30 void build( int root , int L , int R )
     31 {
     32     int Mid = ( L + R ) >> 1;
     33     tree[root].L = L;
     34     tree[root].R = R;
     35     tree[root].flag = 0;
     36     if( L==R )
     37     {
     38         if( str[L]=='1' )
     39         {
     40             tree[root].numOne = 1;
     41             tree[root].numZero = 0;
     42         }
     43         else
     44         {
     45             tree[root].numOne = 0;
     46             tree[root].numZero = 1;
     47         }
     48         return ;
     49     }
     50     build( root<<1 , L , Mid );
     51     build( root<<1|1 , Mid+1 , R );
     52     pushUp( root );
     53 }
     54 
     55 void update( int root , int L , int R )
     56 {
     57     int Mid = ( tree[root].L + tree[root].R ) >> 1;
     58     if( tree[root].L == L && tree[root].R == R )
     59     {
     60         swap( tree[root].numZero , tree[root].numOne );
     61         tree[root].flag ^= 1;
     62         return ;
     63     }
     64     if( tree[root].flag )
     65     {
     66         pushDown( root );
     67         tree[root].flag = 0;
     68     }
     69     if( R<=Mid )
     70         update( root<<1 , L , R );
     71     else if( L>=Mid+1 )
     72         update( root<<1|1 , L , R );
     73     else
     74     {
     75         update( root<<1 , L , Mid );
     76         update( root<<1|1 , Mid+1 , R );
     77     }
     78     pushUp( root );
     79 }
     80 
     81 int query( int root )
     82 {
     83      int ans = -1;
     84      if( tree[root].L == tree[root].R )
     85      {
     86         return tree[root].L;
     87      }
     88      if( tree[root].flag )
     89      {
     90         pushDown( root );
     91         tree[root].flag = 0;
     92      }
     93      if( tree[root<<1].numZero )
     94         ans = query( root<<1 );
     95     else if( tree[root<<1|1].numZero )
     96         ans = query( root<<1|1 );
     97     return ans;
     98 }
     99 
    100 int main()
    101 {
    102     cin.sync_with_stdio(false);
    103     int n , k , cnt , pos;
    104     bool flag;
    105     while( cin >> n >> k && ( n||k ) )
    106     {
    107         cnt = 0;
    108         flag = true;
    109         cin >> (str+1);
    110         build( 1 , 1 , n );
    111         if( tree[1].numOne == n )
    112         {
    113             cout << 0 << endl;
    114         }
    115         else if( !k )
    116         {
    117             cout << -1 << endl;
    118         }
    119         else
    120         {
    121             while(1)
    122             {
    123                pos = query( 1 );
    124                if( pos == -1 )
    125                     break;
    126                 if( pos+k-1>n )
    127                 {
    128                     flag = false;
    129                     break;
    130                 }       
    131                 update( 1 , pos , pos+k-1 );
    132                 ++ cnt;
    133             }
    134             if( flag )
    135                 cout << cnt << endl;
    136             else
    137                 cout << -1 << endl;
    138         }
    139     }
    140     return 0;
    141 }
    View Code

    today:

      小孩子才问你为什么不理我了

      是不是不喜欢我了

      成年人都是默契地相互疏远

    just follow your heart
  • 相关阅读:
    CREATE OPERATOR
    create_module
    一个LINUX狂人的语录(个人认为很精辟)
    jQuery 判断多个 input file 都不能为空
    Java实现 LeetCode 2 两数相加
    Java实现 LeetCode 2 两数相加
    Java实现 LeetCode 2 两数相加
    Java实现 蓝桥杯 算法提高 和谐宿舍2
    Java实现 蓝桥杯 算法提高 和谐宿舍2
    Java实现 蓝桥杯 算法提高 和谐宿舍2
  • 原文地址:https://www.cnblogs.com/radical/p/4074731.html
Copyright © 2011-2022 走看看