题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3397
题意:给你一个长度为n的0,1序列,支持下列五种操作,
操作0(0 a b):将a到b这个区间的元素全部置为0。
操作1(1 a b):将a到b这个区间的元素全部置为1。
操作2(2 a b):将a到b这个区间所有的0置为1,所有的1置为0。
操作3(3 a b):查询a到b这个区间1的总数。
操作4(4 a b):查询a到b这个区间连续1的最长长度
本题属于简单的区间更新线段树
重点:0操作和1操作都属于普通的set操作,可以直接覆盖其他操作,但是2操作需要仔细考虑。操作2在其他的操作之后不能直接采用覆盖的方式,比如(1 left right) (2 left right)的操作序列,如果直接覆盖就变成了(2 left right),而实际上应该变成(0 left right)。大家可以看下代码中的deal_xor函数。
感想:主啊,眼睛都快敲瞎了,敲完还一直wrong,瞬间??。
#include <iostream> #include <cstring> #include <algorithm> #define maxn 400010 #define inf 1000000000 #define LL(x) x<<1 #define RR(x) x<<1|1 using namespace std; typedef long long LL; //variable define struct tree { int l, r; int cnt; int lsum0, rsum0, sum0; int lsum1, rsum1, sum1; int set; }; tree node[maxn]; int n, m; //function define void push_down(int x); void push_up(int x); void build_tree(int left, int right, int x); tree query(int left, int right, int x); void update_set(int left, int right, int x, int val); int deal_xor(int x) { if (node[x].set == -1) return 2; else if (node[x].set == 0) return 1; else if (node[x].set == 1) return 0; else return -1; } int main(void) { int ncase; scanf("%d", &ncase); while (ncase--) { scanf("%d %d", &n, &m); build_tree( 1, n, 1); int op, x, y; while (m--) { scanf("%d %d %d", &op, &x, &y); x += 1; y += 1; if (op == 0) { update_set( x, y, 1, op); } else if (op == 1) { update_set( x, y, 1, op); } else if (op == 2) { update_set( x, y, 1, op); } else if (op == 3) { tree result = query( x, y, 1); printf("%d\n", result.cnt); } else { tree result = query( x, y, 1); printf("%d\n", result.sum1); } } } return 0; } void build_tree(int left, int right, int x) { node[x].l = left; node[x].r = right; node[x].set = -1; if (left == right) { int t; scanf("%d", &t); if (t == 1) { node[x].cnt = node[x].sum1 = node[x].lsum1 = node[x].rsum1 = 1; node[x].sum0 = node[x].lsum0 = node[x].rsum0 = 0; } else { node[x].cnt = node[x].sum1 = node[x].lsum1 = node[x].rsum1 = 0; node[x].sum0 = node[x].lsum0 = node[x].rsum0 = 1; } return; } int lx = LL(x); int rx = RR(x); int mid = left + (right - left)/2; build_tree(left, mid, lx); build_tree(mid + 1, right, rx); push_up(x); } void push_up(int x) { if (node[x].l >= node[x].r) return; int lx = LL(x); int rx = RR(x); node[x].cnt = node[lx].cnt + node[rx].cnt; node[x].sum1 = max( node[lx].rsum1 + node[rx].lsum1, max( node[lx].sum1, node[rx].sum1)); node[x].lsum1 = node[lx].lsum1 == (node[lx].r - node[lx].l + 1) ? node[lx].lsum1 + node[rx].lsum1 : node[lx].lsum1; node[x].rsum1 = node[rx].rsum1 == (node[rx].r - node[rx].l + 1) ? node[rx].rsum1 + node[lx].rsum1 : node[rx].rsum1; node[x].sum0 = max( node[lx].rsum0 + node[rx].lsum0, max( node[lx].sum0, node[rx].sum0)); node[x].lsum0 = node[lx].lsum0 == (node[lx].r - node[lx].l + 1) ? node[lx].lsum0 + node[rx].lsum0 : node[lx].lsum0; node[x].rsum0 = node[rx].rsum0 == (node[rx].r - node[rx].l + 1) ? node[rx].rsum0 + node[lx].rsum0 : node[rx].rsum0; } void push_down(int x) { if (node[x].l >= node[x].r) return; int lx = LL(x); int rx = RR(x); if (node[x].set != -1) { if (node[x].set == 0) { node[lx].cnt = node[lx].sum1 = node[lx].lsum1 = node[lx].rsum1 = 0; node[lx].sum0 = node[lx].lsum0 = node[lx].rsum0 = node[lx].r - node[lx].l + 1; node[rx].cnt = node[rx].sum1 = node[rx].lsum1 = node[rx].rsum1 = 0; node[rx].sum0 = node[rx].lsum0 = node[rx].rsum0 = node[rx].r - node[rx].l + 1; node[lx].set = node[rx].set = 0; } else if (node[x].set == 1) { node[lx].cnt = node[lx].sum1 = node[lx].lsum1 = node[lx].rsum1 = node[lx].r - node[lx].l + 1; node[lx].sum0 = node[lx].lsum0 = node[lx].rsum0 = 0; node[rx].cnt = node[rx].sum1 = node[rx].lsum1 = node[rx].rsum1 = node[rx].r - node[rx].l + 1; node[rx].sum0 = node[rx].lsum0 = node[rx].rsum0 = 0; node[lx].set = node[rx].set = 1; } else { int t1, t2, t3; node[lx].set = deal_xor(lx); node[lx].cnt = node[lx].r - node[lx].l + 1 - node[lx].cnt; t1 = node[lx].sum1; t2 = node[lx].lsum1; t3 = node[lx].rsum1; node[lx].sum1 = node[lx].sum0; node[lx].lsum1 = node[lx].lsum0; node[lx].rsum1 = node[lx].rsum0; node[lx].sum0 = t1; node[lx].lsum0 = t2; node[lx].rsum0 = t3; node[rx].set = deal_xor(rx); node[rx].cnt = node[rx].r - node[rx].l + 1 - node[rx].cnt; t1 = node[rx].sum1; t2 = node[rx].lsum1; t3 = node[rx].rsum1; node[rx].sum1 = node[rx].sum0; node[rx].lsum1 = node[rx].lsum0; node[rx].rsum1 = node[rx].rsum0; node[rx].sum0 = t1; node[rx].lsum0 = t2; node[rx].rsum0 = t3; } } } void update_set(int left, int right, int x, int val) { if (node[x].l == left && node[x].r == right) { if (val == 0) { node[x].cnt = node[x].sum1 = node[x].lsum1 = node[x].rsum1 = 0; node[x].sum0 = node[x].lsum0 = node[x].rsum0 = node[x].r - node[x].l + 1; node[x].set = 0; } else if (val == 1) { node[x].cnt = node[x].sum1 = node[x].lsum1 = node[x].rsum1 = node[x].r - node[x].l + 1; node[x].sum0 = node[x].lsum0 = node[x].rsum0 = 0; node[x].set = 1; } else { node[x].set = deal_xor(x); node[x].cnt = node[x].r - node[x].l + 1 - node[x].cnt; int t1, t2, t3; t1 = node[x].sum1; t2 = node[x].lsum1; t3 = node[x].rsum1; node[x].sum1 = node[x].sum0; node[x].lsum1 = node[x].lsum0; node[x].rsum1 = node[x].rsum0; node[x].sum0 = t1; node[x].lsum0 = t2; node[x].rsum0 = t3; } return; } push_down(x); node[x].set = -1; int lx = LL(x); int rx = RR(x); int mid = node[x].l + (node[x].r - node[x].l)/2; if (right <= mid) update_set(left, right, lx, val); else if (left > mid) update_set(left, right, rx, val); else { update_set(left, mid, lx, val); update_set(mid + 1, right, rx, val); } push_up( x); } tree query(int left, int right, int x) { if (node[x].l == left && node[x].r == right) { return node[x]; } push_down(x); node[x].set = -1; int mid = node[x].l + (node[x].r - node[x].l)/2; int lx = LL(x); int rx = RR(x); tree ans; if (right <= mid) ans = query(left, right, lx); else if (left > mid) ans = query(left, right, rx); else { tree lnode = query(left, mid, lx); tree rnode = query(mid + 1, right, rx); ans.cnt = lnode.cnt + rnode.cnt; ans.sum1 = max( lnode.rsum1 + rnode.lsum1, max( lnode.sum1, rnode.sum1)); ans.lsum1 = lnode.lsum1 == (lnode.r - lnode.l + 1) ? lnode.lsum1 + rnode.lsum1 : lnode.lsum1; ans.rsum1 = rnode.rsum1 == (rnode.r - rnode.l + 1) ? rnode.rsum1 + lnode.rsum1 : rnode.rsum1; ans.sum0 = max( lnode.rsum0 + rnode.lsum0, max( lnode.sum0, rnode.sum0)); ans.lsum0 = lnode.lsum0 == (lnode.r - lnode.l + 1) ? lnode.lsum0 + rnode.lsum0 : lnode.lsum0; ans.rsum0 = rnode.rsum0 == (rnode.r - rnode.l + 1) ? rnode.rsum0 + lnode.rsum0 : rnode.rsum0; } push_up(x); return ans; }
时间: 2024-10-13 21:24:55