1022 小H的询问 端点线段树 区间合法性
链接:https://ac.nowcoder.com/acm/contest/26896/1022
来源:牛客网
题目描述
小H给你一个数组{a},要求支持以下两种操作:
1. 0 l r(1<=l<=r<=n),询问区间[l,r]中权值和最大的有效子区间的权值和,一个子区间被认为是有效的当且仅当这个子区间中没有两个相邻的偶数或者奇数。
2. 1 x v(1<=x<=n,-109<=v<=109),将a[x]的值修改为v。
输入描述:
第一行读入两个正整数n,m(1<=n,m<=105)
第二行读入n个整数,第i个表示a[i](-109 <= a[i] <= 109)
接下来m行,每行三个数表示操作,描述见题目描述。
输出描述:
输出每个询问的答案。
分析
奇偶交错算是合法区间。
lv,rv表示左边界和右边界的奇偶性
ans 表示合法区间值
lsum和rsum表示左区间的合法区间值和右区间的合法区间值,sum如果整个区间是合法的,那就是区间和,如果区间不合法,就是负无穷。只有当左区间的右边界和右区间的左边界不同也就是合法的时候才会用到这个值。就能直接判断整个区间合法不合法了
返回结构体,就不用push_up的时候很麻烦地修改根节点的值了,直接赋值。
//-------------------------代码---------------------------- #define int ll const int N = 1e5+10; int n,m; struct node { int l,r; bool lv,rv; int ans; int lsum,rsum,sum; }tr[N<<2]; int a[N]; node merge(node a,node b) { node c;c.l = a.l;c.r = b.r; c.lv = a.lv;c.rv = b.rv; c.ans = max(a.ans,b.ans); c.lsum = a.lsum;c.rsum = b.rsum;c.sum = -1e18; if(a.rv!=b.lv) { c.ans = max(c.ans,a.rsum + b.lsum); c.lsum = max(c.lsum,a.sum + b.lsum); c.rsum = max(c.rsum,b.sum + a.rsum); c.sum = max(c.sum,a.sum + b.sum); } return c; } void build(int u,int l,int r) { tr[u].l = l;tr[u].r = r; if(l == r) { tr[u].lsum = tr[u].rsum = tr[u].sum = tr[u].ans = a[l]; tr[u].lv = tr[u].rv = abs(a[l] % 2);rt; } build(ul,l,tr_mid);build(ur,tr_mid+1,r); tr[u] = merge(tr[ul],tr[ur]); } void modify(int u,int pos,int v) { if(tr[u].l == tr[u].r) { tr[u].lsum = tr[u].rsum = tr[u].sum = tr[u].ans = v; tr[u].lv = tr[u].rv = abs(v % 2);rt; } if(pos <= tr_mid) modify(ul,pos,v); else modify(ur,pos,v); tr[u] = merge(tr[ul],tr[ur]); } node query(int u,int l,int r) { if(l<=tr[u].l && tr[u].r <=r) return tr[u]; if(r <= tr_mid) return query(ul,l,r); if(tr_mid < l) return query(ur,l,r); return merge(query(ul,l,r),query(ur,l,r)); } void solve() { cin>>n>>m; fo(i,1,n) cin>>a[i]; build(1,1,n); while(m--) { int op,l,r;cin>>op>>l>>r; if(op == 0) cout<<query(1,l,r).ans<<endl; else { modify(1,l,r); } } } void main_init() {} signed main(){ AC();clapping();TLE; cout<<fixed<<setprecision(12); main_init(); // while(cin>>n,n) // while(cin>>n>>m,n,m) // int t;cin>>t;while(t -- ) solve(); // {solve(); } return 0; } /*样例区 */ //------------------------------------------------------------