Codeforces Round #425 (Div. 2) D 树链剖分 + 树状数组维护区间
2017-07-29 12:30
316 查看
一看就知道 可以LCA判断做 也可以树链剖分拿头暴力
然而快速读入和线段树维护区间会T70 于是只能LCA?
线段树的常数不小 于是需要另外一种办法来进行区间加减和查询区间和 就是使用树状数组
这个题的代码
其中的树状数组 拿两个数组来分别维护 具体代码
树状数组天下无敌TAT 于是又上网学习了新姿势 我有姿势我自豪
树状数组单点修改 + 区间查询max
以及这里还有...矩形增减 + 矩形查询和的黑科技。。。
http://blog.csdn.net/lawrence_jang/article/details/8054173
然而快速读入和线段树维护区间会T70 于是只能LCA?
线段树的常数不小 于是需要另外一种办法来进行区间加减和查询区间和 就是使用树状数组
这个题的代码
#include<iostream> #include<cstdio> #include<cmath> #include<algorithm> #include<vector> #include<cstring> using namespace std; #define pb push_back int n , qn ; vector<int > q [100050] ; int top[100050] , fa[100050] , deep[100050] , num[100050] , p[100050] , fp[100050] , son[100050] , pos ; inline int read() { int x=0;char ch=getchar(); while(ch<'0'||ch>'9')ch=getchar(); while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x; } ///---------- int c[100050] ; int d[100050] ; int lowbit(int x) { return (x & (-x)) ; } void add(int c[] , int x ,int val) { while(x <= n+5) { c[x] += val ; x += lowbit(x) ; } } int sum(int c[] , int x) { int res = 0 ; while(x > 0) { res += c[x] ; x -= lowbit(x) ; } return res ; } void add(int l , int r , int val) { add(c , l , val) ; add(d , l , l * val) ; add(c , r+1 , -val ) ; add(d , r + 1 , -val * (r+1)) ; } int sum(int x) { return (x + 1) * sum(c , x) - sum(d , x) ; } int sum(int l , int r) { return sum(r) - sum(l - 1) ; } ///---------- void dfs1(int u , int pre , int d) { deep[u] = d ; fa[u] = pre ; num[u] = 1 ; for(int i = 0 ; i < q[u].size() ; i ++ ) { int v = q[u][i] ; if(v != pre) { dfs1(v , u , d+1) ; num[u] += num[v] ; if(son[u] == -1 || num[v] > num[son[u]]) { son[u] = v ; } } } } void getpos(int u , int sp) { top[u] = sp ; p[u] = pos ++ ; fp[p[u]] = u ; if(son[u] == -1) return ; getpos(son[u] , sp) ; for(int i = 0 ; i < q[u].size() ; i ++ ) { int v = q[u][i] ; if(v != son[u] && v != fa[u]) { getpos(v , v) ; } } } void chang(int u , int v , int val) { int f1 = top[u] , f2 = top[v] ; int tmp = 0 ; while(f1 != f2) { if(deep[f1] < deep[f2]) { swap(f1 , f2) ; swap(u , v) ; } add(p[f1] , p[u] , val) ; u = fa[f1] ; f1 = top[u] ; } if(deep[u] > deep[v]) swap(u , v) ; add(p[u] , p[v] , val) ; } int que(int u , int v) { int f1 = top[u] , f2 = top[v] ; int tmp = 0 ; while(f1 != f2) { if(deep[f1] < deep[f2]) { swap(f1 , f2) ; swap(u , v) ; } tmp += sum(p[f1] , p[u]) ; u = fa[f1] ; f1 = top[u] ; } if(deep[u] > deep[v]) swap(u , v) ; tmp += sum(p[u] , p[v]) ; return tmp ; } int main () { n = read() ; qn = read() ; for(int i = 2 ; i <= n ; i ++ ) { int z ; z = read() ; q[z].pb(i) ; q[i].pb(z) ; } memset(son , -1 , sizeof(son)) ; pos = 1 ; dfs1(1,0,0) ; getpos(1 , 1) ; while(qn -- ) { int aa , bb , cc ; aa = read() ; bb = read() ; cc = read() ; int ans = 0 ; chang(aa,bb,1) ; ans = max(que(bb,cc) , ans) ; chang(aa,bb,-1) ; chang(aa,cc,1) ; ans = max(que(bb,cc) , ans) ; chang(aa,cc,-1) ; chang(aa,bb,1) ; ans = max(que(aa,cc) , ans) ; chang(aa,bb,-1) ; printf("%d\n" , ans) ; } }
其中的树状数组 拿两个数组来分别维护 具体代码
int c[100050] ; int d[100050] ; int lowbit(int x) { return (x & (-x)) ; } void add(int c[] , int x ,int val) { while(x <= n+5) { c[x] += val ; x += lowbit(x) ; } } int sum(int c[] , int x) { int res = 0 ; while(x > 0) { res += c[x] ; x -= lowbit(x) ; } return res ; } void add(int l , int r , int val) { add(c , l , val) ; add(d , l , l * val) ; add(c , r+1 , -val ) ; add(d , r + 1 , -val * (r+1)) ; } int sum(int x) { return (x + 1) * sum(c , x) - sum(d , x) ; } int sum(int l , int r) { return sum(r) - sum(l - 1) ; }
树状数组天下无敌TAT 于是又上网学习了新姿势 我有姿势我自豪
树状数组单点修改 + 区间查询max
int num[5000] ; int c[5000] ; int n ; int lowbit(int x) { return x & (-x); } void updata(int x) { int lx, i; while (x <= n) { c[x] = num[x]; lx = lowbit(x); for (i=1; i<lx; i<<=1) c[x] = max(c[x], c[x-i]); x += lowbit(x); } } int query(int L, int R) { int ans = 0; while (R >= L) { ans = max(num[R], ans); R --; for (; R-lowbit(R) >= L; R -= lowbit(R)) ans = max(c[R], ans); } return ans; }
以及这里还有...矩形增减 + 矩形查询和的黑科技。。。
http://blog.csdn.net/lawrence_jang/article/details/8054173
相关文章推荐
- hdu3966Aragorn's Story(树链剖分+树状数组维护区间)
- 【Codeforces Round 169 (Div 2) E】【数据结构区间维护】Little Girl and Problem on Trees 大菊花树的距离性修改查询
- BZOJ 3221 [Codechef FEB13] Obserbing the tree树上询问 树链剖分 主席树维护区间加等差数列
- poj3237(树链剖分边维护+线段树区间更新)
- BNUOJ39566 Do use segment tree (树链剖分+维护区间最大连续和)
- LA 4329 树状数组(BIT) 维护更新一段区间的前缀和
- 区间信息的维护和查询系列算法-树状数组
- BZOJ-4811: [Ynoi2017]由乃的OJ (树链剖分 线段树维护区间操作值 好题)
- gym101138J(树链剖分,线段树维护区间连续子段最大和,好题)
- Codeforces Round #425 (Div. 2) Problem D Misha, Grisha and Underground (Codeforces 832D) - 树链剖分 - 树状数组
- 【转载】区间信息的维护与查询(一)——二叉索引树(Fenwick树、树状数组)
- 校赛H题 tree 树链剖分维护区间平方的和
- BZOJ-2243: [SDOI2011]染色 (树链剖分 入门题 线段树 区间修改查询 维护端点值)
- 【Codeforces】Codeforces Round #299 (Div. 1) E. Tavas on the Path 【树链剖分+区间合并】
- Codeforces Round #376 (Div. 2) D 线段树区间维护
- 树状数组区间维护及单点查询
- 【树链剖分+树状数组区间修改区间和】BZOJ4034(LOJ#2125)[HAOI2015]树上操作
- poj3264 树状数组维护区间最值
- 【LuoguP3038/[USACO11DEC]牧草种植Grass Planting】树链剖分+树状数组【树状数组的区间修改与区间查询】
- Codeforces 588E Duff in the Army 【树链剖分维护区间前k小】