线段树区间更新:
//0 x y v: [x ,y ]内元素都加上v
//1 x y : [x ,y ]内元素的和
typedef long long ll;
const int N = 100010 ;
struct node
{
int l, r;
ll val, mark;
}tr [N*4 ];
int cas = 0 ;
void push_up(int k)
{
tr [k].val = tr [k<<1 ].val + tr [k<<1 |1 ].val;
}
void push_down(int k)
{
if (tr [k].mark)
{
tr [k<<1 ].mark += tr [k].mark, tr [k<<1 |1 ].mark += tr [k].mark;
tr [k<<1 ].val += (tr [k<<1 ].r - tr [k<<1 ].l + 1 ) * tr [k].mark;
tr [k<<1 |1 ].val += (tr [k<<1 |1 ].r - tr [k<<1 |1 ].l + 1 ) * tr [k].mark;
tr [k].mark = 0 ;
}
}
void build(int l, int r, int k)
{
tr [k].l = l, tr [k].r = r, tr [k].mark = 0 ;
if (l == r)
{
tr [k].val = 0 ; return ;
}
int mid = (l + r) >> 1 ;
build(l, mid, k << 1 );
build(mid + 1 , r, k << 1 |1 );
push_up(k);
}
void update(int l, int r, int val, int k)
{
if (l <= tr [k].l && tr [k].r <= r)
{
tr [k].mark += val;
tr [k].val += 1 LL * (tr [k].r - tr [k].l + 1 ) * val;
return ;
}
push_down(k);
int mid = (tr [k].l + tr [k].r) >> 1 ;
if (l <= mid) update(l, r, val, k << 1 );
if (r > mid) update(l, r, val, k << 1 |1 );
push_up(k);
}
ll query(int l, int r, int k)
{
if (l <= tr [k].l && tr [k].r <= r) return tr [k].val;
push_down(k);
int mid = (tr [k].l + tr [k].r) >> 1 ;
ll res = 0 ;
if (l <= mid) res += query(l, r, k << 1 );
if (r > mid) res += query(l, r, k << 1 |1 );
return res;
}
int main()
{
int t, n, m , a, b, c, d;
scanf("%d " , &t);
while (t--)
{
scanf("%d %d " , &n, &m );
build(1 , n, 1 );
printf ("Case %d :\n" , ++cas);
for (int i = 0 ; i < m ; i++)
{
scanf("%d " , &a);
if (a == 0 )
{// 下标从0 开始,故+1
scanf("%d %d %d " , &b, &c, &d);
update(b+1 , c+1 , d, 1 );
}
else
{
scanf("%d %d " , &b, &c);
printf ("%lld \n" , query(b+1 , c+1 , 1 ));
}
}
}
return 0 ;
}
线段树区间合并:
using namespace std;
// 给定一个长度为n的01 串,接下来一个m ,有m 个操作,操作有两种:0 a b查询区间内最长连续1 的长度,1 a b反转区间内,0 变1 ,1 变0
const int N = 100010 ;
struct node
{
int l, r;
int lone, lzero, rone, rzero, max1, max0 ;// 分别维护左起1 ,左起0 ,右起1 ,右起0 ,区间中1 的最大长度,0 的最大长度
int len, mark; // 区间长度,lazy标记
}tr [N*4 ];
int val[N];
void push_up(int k)
{
tr [k].lone = tr [k<<1 ].lone;
if (tr [k<<1 ].lone == tr [k<<1 ].len) tr [k].lone += tr [k<<1 |1 ].lone;// 左子树左起1 的长度等于区间长度,那么直接加上右子树的左起1 长度
tr [k].lzero = tr [k<<1 ].lzero;
if (tr [k<<1 ].lzero == tr [k<<1 ].len) tr [k].lzero += tr [k<<1 |1 ].lzero;
tr [k].rone = tr [k<<1 |1 ].rone;
if (tr [k<<1 |1 ].rone == tr [k<<1 |1 ].len) tr [k].rone += tr [k<<1 ].rone;
tr [k].rzero = tr [k<<1 |1 ].rzero;
if (tr [k<<1 |1 ].rzero == tr [k<<1 |1 ].len) tr [k].rzero += tr [k<<1 ].rzero;
tr [k].max1 = max(tr [k<<1 ].rone + tr [k<<1 |1 ].lone, max(tr [k<<1 ].max1, tr [k<<1 |1 ].max1));
tr [k].max0 = max(tr [k<<1 ].rzero + tr [k<<1 |1 ].lzero, max(tr [k<<1 ].max0 , tr [k<<1 |1 ].max0 ));
}
void push_down(int k)
{
if (tr [k].mark)//0 与1 互变,所以所有的维护信息也要互换
{
tr [k<<1 ].mark ^= tr [k].mark;
tr [k<<1 |1 ].mark ^= tr [k].mark;
swap(tr [k<<1 ].lone, tr [k<<1 ].lzero);
swap(tr [k<<1 ].rone, tr [k<<1 ].rzero);
swap(tr [k<<1 ].max1, tr [k<<1 ].max0 );
swap(tr [k<<1 |1 ].lone, tr [k<<1 |1 ].lzero);
swap(tr [k<<1 |1 ].rone, tr [k<<1 |1 ].rzero);
swap(tr [k<<1 |1 ].max1, tr [k<<1 |1 ].max0 );
tr [k].mark = 0 ;
}
}
void build(int l, int r, int k)
{
tr [k].l = l, tr [k].r = r, tr [k].mark = 0 , tr [k].len = r - l + 1 ;
if (l == r)
{
if (val[l]) tr [k].lone = tr [k].rone = tr [k].max1 = 1 , tr [k].lzero = tr [k].rzero = tr [k].max0 = 0 ;
else tr [k].lzero = tr [k].rzero = tr [k].max0 = 1 , tr [k].lone = tr [k].rone = tr [k].max1 = 0 ;
return ;
}
int mid = (tr [k].l + tr [k].r) >> 1 ;
build(l, mid, k << 1 );
build(mid + 1 , r, k << 1 | 1 );
push_up(k);
}
void update(int l, int r, int k)
{
if (l <= tr [k].l && tr [k].r <= r)
{
tr [k].mark ^= 1 ;
swap(tr [k].rone, tr [k].rzero);
swap(tr [k].lone, tr [k].lzero);
swap(tr [k].max1, tr [k].max0 );
return ;
}
push_down(k);
int mid = (tr [k].l + tr [k].r) >> 1 ;
if (l <= mid) update(l, r, k << 1 );
if (r > mid) update(l, r, k << 1 | 1 );
push_up(k);
}
int query(int l, int r, int k)
{
if (l == tr [k].l && tr [k].r == r)
return tr [k].max1;
push_down(k);
int mid = (tr [k].l + tr [k].r) >> 1 ;
if (r <= mid) return query(l, r, k << 1 ); // 查询区间位于左子树
else if (l > mid) return query(l, r, k << 1 | 1 ); // 查询区间位于右子树
else //查询区间被分割
{
int left = 0 , right = 0 , midd = 0 ;
midd = min(mid - l + 1 , tr [k<<1 ].rone) + min(r - mid, tr [k<<1 |1 ].lone);
left = query(l, mid, k << 1 );
right = query(mid + 1 , r, k << 1 | 1 );
return max(midd, max(left, right));
}
}
int main()
{
int n, m , a, b, c;
while (~ scanf("%d " , &n))
{
for (int i = 1 ; i <= n; i++)
scanf("%d " , val + i);
build(1 , n, 1 );
scanf("%d " , &m );
for (int i = 0 ; i < m ; i++)
{
scanf("%d %d %d " , &a, &b, &c);
if (a) update(b, c, 1 );
else printf ("%d \n" , query(b, c, 1 ));
}
}
return 0 ;
}