Can you answer these queries VII 【SPOJ - GSS7】【树链剖分 最大子段和】
2019-08-12 08:58
1336 查看
题目链接
造了好多组样例,最后的时候发现,竟然是update的时候区间的更新并没有完全更新到位,导致最后变成WA了,竟然是WA了后面的几组,还让我一度以为是找区间的时候出现了问题。
然后剩下的就是一些简单的线段树了,最难处理的不过是在树上公公祖先的那部分,debug200+行的代码真的挺难的,尤其是今早的时候灵光闪现!
[code]#include <iostream> #include <cstdio> #include <cmath> #include <string> #include <cstring> #include <algorithm> #include <limits> #include <vector> #include <stack> #include <queue> #include <set> #include <map> #define lowbit(x) ( x&(-x) ) #define pi 3.141592653589793 #define e 2.718281828459045 #define INF 0x3f3f3f3f #define efs 1e-6 #define HalF (l + r)>>1 #define lsn rt<<1 #define rsn rt<<1|1 #define Lson lsn, l, mid #define Rson rsn, mid+1, r #define QL Lson, ql, qr #define QR Rson, ql, qr #define myself rt, l, r #define max3(a, b, c) max(a, max(b, c)) #define max4(a, b, c, d) max(max(a, b), max(c, d)) #define max5(a, b, c, d, f) max4(a, b, c, max(d, f)) #define max6(a, b, c, d, f, g) max(max3(a, b, c), max3(d, f, g)) using namespace std; typedef unsigned long long ull; typedef long long ll; const int maxN = 1e5 + 7; int N, Q, head[maxN], cnt, a[maxN], tot; struct Eddge { int nex, to; Eddge(int a=-1, int b=0):nex(a), to(b) {} }edge[maxN<<1]; inline void addEddge(int u, int v) { edge[cnt] = Eddge(head[u], v); head[u] = cnt++; } inline void _add(int u, int v) { addEddge(u, v); addEddge(v, u); } int root[maxN], deep[maxN], siz[maxN], W_son[maxN]; void dfs1(int u, int fa, int depth) { root[u] = fa; deep[u] = depth; siz[u] = 1; W_son[u] = -1; int maxx = 0; for(int i=head[u], v; ~i; i=edge[i].nex) { v = edge[i].to; if(v == fa) continue; dfs1(v, u, depth + 1); siz[u] += siz[v]; if(siz[v] > maxx) { maxx = siz[v]; W_son[u] = v; } } } int top[maxN], id[maxN], w[maxN]; void dfs2(int u, int topf) { top[u] = topf; id[u] = ++tot; w[tot] = a[u]; if(W_son[u] == -1) return; dfs2(W_son[u], topf); for(int i=head[u], v; ~i; i=edge[i].nex) { v = edge[i].to; if(v == root[u] || v == W_son[u]) continue; dfs2(v, v); } } struct node { int lm, rm, mx, all, lazy; bool op; node() { lm = rm = mx = all = lazy = 0; op = false; } void give(int x) { lm = rm = mx = all = x; } }tree[maxN<<2]; inline void pushdown(int rt, int l, int r) { if(tree[rt].op) { int mid = HalF; tree[lsn].mx = tree[lsn].rm = tree[lsn].lm = (tree[rt].lazy > 0 ? tree[rt].lazy * (mid - l + 1) : tree[rt].lazy); tree[rsn].mx = tree[rsn].rm = tree[rsn].lm = (tree[rt].lazy > 0 ? tree[rt].lazy * (r - mid) : tree[rt].lazy); tree[lsn].all = tree[rt].lazy * (mid - l + 1); tree[rsn].all = tree[rt].lazy * (r - mid); tree[lsn].lazy = tree[rsn].lazy = tree[rt].lazy; tree[rt].lazy = 0; tree[rt].op = false; tree[lsn].op = tree[rsn].op = true; } } inline void pushup(node &rt, node lc, node rc) { rt.lm = max(lc.lm, lc.all + rc.lm); rt.rm = max(rc.rm, rc.all + lc.rm); rt.all = lc.all + rc.all; rt.mx = max3(lc.mx, rc.mx, lc.rm + rc.lm); } void buildTree(int rt, int l, int r) { if(l == r) { tree[rt].give(w[l]); return; } int mid = HalF; buildTree(Lson); buildTree(Rson); pushup(tree[rt], tree[lsn], tree[rsn]); } void update(int rt, int l, int r, int ql, int qr, int val) { if(ql <= l && qr >= r) { tree[rt].lm = tree[rt].rm = tree[rt].mx = ( val > 0 ? val * (r - l + 1) : val ); tree[rt].op = true; tree[rt].lazy = val; tree[rt].all = val * (r - l + 1); return; } pushdown(myself); int mid = HalF; if(qr <= mid) update(QL, val); else if(ql > mid) update(QR, val); else { update(QL, val); update(QR, val); } pushup(tree[rt], tree[lsn], tree[rsn]); } node query(int rt, int l, int r, int ql, int qr) { if(ql <= l && qr >= r) return tree[rt]; pushdown(myself); int mid = HalF; if(qr <= mid) return query(QL); else if(ql > mid) return query(QR); else { node TL = query(QL), TR = query(QR), ans; pushup(ans, TL, TR); return ans; } } inline int query_range(int x, int y) { node TX, TY, tmp; while(top[x] != top[y]) { if(deep[top[x]] > deep[top[y]]) //走x { tmp = query(1, 1, N, id[top[x]], id[x]); pushup(TX, query(1, 1, N, id[top[x]], id[x]), TX); x = root[top[x]]; } else //走y { pushup(TY, query(1, 1, N, id[top[y]], id[y]), TY); y = root[top[y]]; } } if(deep[x] > deep[y]) { pushup(TX, query(1, 1, N, id[y], id[x]), TX); } else { pushup(TY, query(1, 1, N, id[x], id[y]), TY); } return max4(0, TY.mx, TX.mx, TX.lm + TY.lm); } inline void updata_range(int x, int y, int w) { while(top[x] != top[y]) { if(deep[top[x]] < deep[top[y]]) swap(x, y); update(1, 1, N, id[top[x]], id[x], w); x = root[top[x]]; } if(deep[x] < deep[y]) swap(x, y); update(1, 1, N, id[y], id[x], w); } inline void init() { cnt = tot = 0; for(int i=1; i<=N; i++) head[i] = -1; } int main() { scanf("%d", &N); init(); for(int i=1; i<=N; i++) scanf("%d", &a[i]); for(int i=1, u, v; i<N; i++) { scanf("%d%d", &u, &v); _add(u, v); } dfs1(1, 1, 0); dfs2(1, 1); buildTree(1, 1, N); scanf("%d", &Q); int ch, a, b, c; while(Q--) { scanf("%d%d%d", &ch, &a, &b); if(ch == 1) printf("%d\n", query_range(a, b)); else { scanf("%d", &c); updata_range(a, b, c); } } return 0; } /* 8 0 -2 3 -1 1 5 -10 2 1 2 1 3 2 4 2 5 3 6 6 7 6 8 */
相关文章推荐
- Spoj 6779 Can you answer these queries VII 树链剖分 在树上任意路径的最大子段和 区间修改点权
- SPOJ GSS7 Can you answer these queries VII ——树链剖分 线段树
- spoj(GSS3) 1716 Can you answer these queries III(线段树求最大子段和)
- SPOJ-GSS7 Can you answer these queries VII(树上区间最大和)
- 【SPOJ】6779 Can you answer these queries VII 树链剖分+线段树 求树上的最大子段和
- GSS1 spoj 1043 Can you answer these queries I 最大子段和
- 【SPOJ-GSS1】Can you answer these queries I【线段树】【最大子段和】
- Spoj 1716 Can you answer these queries III 线段树 单点修改 区间求最大子段和
- GSS7 spoj 6779. Can you answer these queries VII 树链剖分+线段树
- Splay树(插入、删除、区间最大字段和)—— SPOJ - GSS6 Can you answer these queries VI
- SPOJGSS7 Can you answer these queries VII
- Spoj 1557 Can you answer these queries II 线段树 任意区间最大子段和 不重复数字
- Spoj 2916 Can you answer these queries V 线段树 求任意重叠区间的最大子段和
- spoj 6779. Can you answer these queries VII(树链剖分)
- SPOJ 6779 Can you answer these queries VII 树链剖分
- Spoj 1557 Can you answer these queries II 线段树 随意区间最大子段和 不反复数字
- SPOJ GSS7 Can you answer these queries VII(LCT)
- SPOJ GSS1 Can you answer these queries I (线段树求区间最大连续和)
- SPOJ GSS1 Can you answer these queries I
- GSS1 - Can you answer these queries I(动态查询区间最大连续和)