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
原文地址:https://www.cnblogs.com/radical/p/4074731.html