【BZOJ1858】【SCOI2010】序列操作 线段树

好累啊,不想写题解了,直接发别人的了。

By:smallling

这题我很二的折腾了一下午,唉,还是太弱了。这题的关键在于标记的更新与更新每个点的权值,更新标记我很快就写好了,思路很清晰,但是查找答案就头晕了,在处理下传标记、更新权值中纠结。。。。

这题我用sum来记录一段区间内1的个数,lseg记录该区间从左往右连续的1的个数,rseg记录该区间从右往左连续的1的个数,seg记录记录该区间中最长的连续1的长度。0同理用另一个数组记录。

下面考虑两个区间的合并,1的个数的合并很简单,直接将权值累加即可。最长连续的1的个数就有点麻烦了,一种情况就是直接从两个区间的seg的最大值继承过来,但这不一定是最优的,因为还有一种可能,就是左边区间的rseg+右边区间的lseg,这可能比之前的最大值更优。lseg的值可以先从左边区间的lest继承过来,如果左边区间的lseg=左边区间的总长度,说明当前区间的lseg还能扩展到右边区间,那么只要左边区间的lseg+右边区间的lseg即可。处理rseg反向考虑一下即可。

接下来考虑修改操作的合并,不难发现覆盖操作的优先级比取反高,因此如果当前操作是覆盖,直接覆盖之前的操作即可。如果是取反,那么也很好想,用1覆盖后在取反,不就是用0覆盖,用0覆盖后取反,就是用1覆盖,取反后再取反,就相当于没有取反~~lazy标记同理即可~是不是很简单

再接下来我们考虑对于每个记录我们该如何操作。也许你会问之前记录0是干嘛的,在这里就要发挥用处啦。如果当前是用1或0全部覆盖,那么把1或0的sum,lseg,rseg,seg全部赋为当前区间的长度即可。如果是取反,就是把0的信息给1,1的信息给0,直接交换0,1的sum,lseg,rseg,seg,是不是也很简单~~~~

之后就是坑爹的ADD和ASK了。。这个大家不同的线段树有不同的写法,我也不详说,注意一下下传标记和区间信息的更新。。还有就是求最长连续1的时候,左右合并要注意长度不能大于当前mid-l+1和r-mid。

原文地址:http://www.cnblogs.com/smallling/p/3695072.html。

代码是自己的。

  1 #include <iostream>
  2 #include <cstdlib>
  3 #include <cstdio>
  4 #include <cstring>
  5 
  6 using namespace std;
  7 
  8 const int N = 400000 + 5;
  9 
 10 namespace SGT{
 11     #define lson rt<<1,l,mid
 12     #define rson rt<<1|1,mid+1,r
 13     int sum[N];
 14     int lseg[N][2], rseg[N][2], seg[N][2];
 15     int same[N], rev[N];
 16     void pushup( int rt, int len1, int len2 ){
 17         int ls = rt<<1, rs = rt<<1|1;
 18         sum[rt] = sum[ls]+sum[rs];
 19         for ( int i = 0; i < 2; i ++ ){
 20             seg[rt][i] = max(seg[ls][i],seg[rs][i]);
 21             seg[rt][i] = max(seg[rt][i],rseg[ls][i]+lseg[rs][i]);
 22             lseg[rt][i] = lseg[ls][i];
 23             rseg[rt][i] = rseg[rs][i];
 24             if ( sum[ls] == len1*i ) lseg[rt][i] += lseg[rs][i];
 25             if ( sum[rs] == len2*i ) rseg[rt][i] += rseg[ls][i];
 26         }
 27     }
 28     void set_same( int rt, int u, int len ){
 29         int v = !u;
 30         same[rt] = u, rev[rt] = 0;
 31         sum[rt] = u*len;
 32         seg[rt][u] = lseg[rt][u] = rseg[rt][u] = len;
 33         seg[rt][v] = lseg[rt][v] = rseg[rt][v] = 0;
 34     }
 35     void set_rev( int rt, int len ){
 36         if ( same[rt] == -1 ){
 37             rev[rt] ^= 1;
 38             sum[rt] = len-sum[rt];            
 39             swap(seg[rt][0],seg[rt][1]);
 40             swap(lseg[rt][0],lseg[rt][1]);
 41             swap(rseg[rt][0],rseg[rt][1]);
 42         }else set_same(rt,!same[rt],len);
 43     }
 44     void pushdown( int rt, int l, int r ){
 45         int ls = rt<<1, rs = rt<<1|1;
 46         int mid = (l + r) >> 1;
 47         if ( same[rt] != -1 ){
 48             set_same(ls,same[rt],mid-l+1);
 49             set_same(rs,same[rt],r-mid);
 50             same[rt] = -1;
 51         }
 52         if ( rev[rt] ){
 53             set_rev(ls,mid-l+1);
 54             set_rev(rs,r-mid);
 55             rev[rt] = 0;
 56         }
 57     }
 58     void build( int rt, int l, int r ){
 59         same[rt] = -1;
 60         if ( l == r ){
 61             scanf( "%d", &sum[rt] );
 62             int w = sum[rt];
 63             seg[rt][w] = lseg[rt][w] = rseg[rt][w] = 1;
 64             return;
 65         }
 66         int mid = (l + r) >> 1;
 67         build(lson), build(rson);
 68         pushup(rt,mid-l+1,r-mid);
 69     }
 70     void update( int rt, int l, int r, int ql, int qr, int type ){
 71         if ( ql <= l && r <= qr ){
 72             if ( type <= 1 ) set_same(rt,type,r-l+1);
 73             else set_rev(rt,r-l+1);
 74             return;
 75         }
 76         pushdown(rt,l,r);
 77         int mid = (l + r) >> 1;
 78         if ( ql <= mid ) update(lson,ql,qr,type);
 79         if ( qr >  mid ) update(rson,ql,qr,type);
 80         pushup(rt,mid-l+1,r-mid);
 81     }
 82     int qsum( int rt, int l, int r, int ql, int qr ){
 83         if ( ql <= l && r <= qr ) return sum[rt];
 84         pushdown(rt,l,r);
 85         int mid = (l + r) >> 1, ret = 0;
 86         if ( ql <= mid ) ret += qsum(lson,ql,qr);
 87         if ( qr >  mid ) ret += qsum(rson,ql,qr);
 88         return ret;
 89     }
 90     struct Node{
 91         int l, r, w;
 92         Node( int l=0, int r=0, int w=0 ):l(l),r(r),w(w){}
 93     };
 94     Node qseg( int rt, int l, int r, int ql, int qr ){
 95         if ( l == ql && r == qr ) return Node(lseg[rt][1],rseg[rt][1],seg[rt][1]);
 96         pushdown(rt,l,r);
 97         int mid = (l + r) >> 1;
 98         if ( qr <= mid ) return qseg(lson,ql,qr);
 99         if ( ql >  mid ) return qseg(rson,ql,qr);
100         Node t1 = qseg(lson,ql,mid), t2 = qseg(rson,mid+1,qr), t;
101         if ( t1.l == mid-l+1 ) t.l = t1.l+t2.l;else t.l = t1.l;
102         if ( t2.r == r - mid ) t.r = t1.r+t2.r;else t.r = t2.r;
103         t.w = max(max(t1.w,t2.w),t1.r+t2.l);
104         return t;
105     }
106 }
107 int n, m, t, x, y;
108 int main(){
109     scanf( "%d%d", &n, &m );
110     SGT::build(1, 1, n);
111     
112     while ( m -- ){
113         scanf( "%d%d%d", &t, &x, &y );++x, ++y;
114         if ( t <= 2 ) SGT::update(1,1,n,x,y,t);
115         if ( t == 3 ) printf( "%d\n", SGT::qsum(1,1,n,x,y) );
116         if ( t == 4 ) printf( "%d\n", SGT::qseg(1,1,n,x,y).w );
117     }
118     return 0;
119 }
View Code

 

posted @ 2016-03-30 19:58  羁旅  阅读(112)  评论(0编辑  收藏  举报