zoukankan      html  css  js  c++  java
  • zkw线段树 小记

    只保证自己看得懂。


    听说与普通线段树相比,zkw发明的这玩意儿更快更短OrzOrzOrz,那就学吧。

    1. 建树

    设数组大小为 (n) ,叶结点个数为 (N)
    zkw线段树为一颗满二叉树,故 (N = 2^{leftlceillog_2 n ight ceil})
    建树可以这么写:

    N = 1;
    while (N < n) N <<= 1;
    for (int i = N; i < N + n; ++i)
    	s[i] = Read();
    for (int i = N - 1; i; --i)
    	s[i] = s[i << 1] + s[i << 1 | 1];
    

    2. 单点修改+区间查询

    只说区间查询,设区间为 ([x,y]) ,令 (l = N + x - 1,r = N + y - 1)
    先令 (ans gets s_l + s_r)
    然后不断进行下面过程:

    1. 判断 (l)(r) 父亲是否相同,相同时 (l oplus r = 1)
    2. (l) 为其父亲的左儿子,则 (ans) 加上其父亲右儿子的值。
      (r) 为其父亲的右儿子,则 (ans) 加上其父亲左儿子的值。
    3. (l getsleftlfloordfrac{l}{2} ight floor,rgets leftlfloordfrac{r}{2} ight floor)

    直接放代码了。
    例题:Luogu P3374

    #include <cstdio>
    #include <cctype>
    #define MAX_N (500000 + 5)
    
    int n, N = 1, m;
    long long s[MAX_N * 3];
    
    int Read() {
    	int res = 0, sign = 0;
    	char ch = getchar();
    	while (!isdigit(ch)) sign |= ch == '-', ch = getchar();
    	while (isdigit(ch)) res = res * 10 + ch - '0', ch = getchar();
    	return sign ? -res : res;
    }
    
    int main() {
    	n = Read(), m = Read();
    	while (N < n) N <<= 1;
    	for (int i = N; i < N + n; ++i)
    		s[i] = Read();
    	for (int i = N - 1; i; --i)
    		s[i] = s[i << 1] + s[i << 1 | 1];
    	int opt, x, y;
    	long long ans;
    	while (m--) {
    		opt = Read(), x = Read(), y = Read();
    		if (opt == 1) {
    			for (int i = N + x - 1; i; i >>= 1)
    				s[i] += y;
    		} else {
    			ans = s[N + x - 1] + s[N + y - 1];
    			for (int l = N + x - 1, r = N + y - 1; l ^ r ^ 1; l >>= 1, r >>= 1) {
    				if (~l & 1) ans += s[l ^ 1];
    				if (r & 1) ans += s[r ^ 1];
    			}
    			printf("%lld
    ", ans);
    		}
    	}
    	return 0;
    }
    

    3. 区间修改+区间查询

    加上标记永久化即可。
    即每次操作要修改自己的父亲,如果 (l,r) 父亲不同还可能要修改父亲的左(右)儿子。
    对着上一个区间查询来改就好了。
    注意这里 (l,r) 要一直上传直到父亲为根结点。
    也是直接放代码了。
    例题:Luogu P3372

    #include <cstdio>
    #include <cctype>
    #define MAX_N (100000 + 5)
    typedef long long LL;
    
    int n, N = 1, m;
    LL s[MAX_N * 3], t[MAX_N * 3];
    
    int Read() {
    	int res = 0, sign = 0;
    	char ch = getchar();
    	while (!isdigit(ch)) sign |= ch == '-', ch = getchar();
    	while (isdigit(ch)) res = res * 10 + ch - '0', ch = getchar();
    	return sign ? -res : res;
    }
    
    int main() {
    	n = Read(), m = Read();
    	while (N < n) N <<= 1;
    	for (int i = N; i < N + n; ++i)
    		s[i] = Read();
    	for (int i = N - 1; i; --i)
    		s[i] = s[i << 1] + s[i << 1 | 1];
    	int opt, x, y, k;
    	LL ans;
    	while (m--) {
    		opt = Read(), x = Read(), y = Read();
    		if (opt == 1) {
    			k = Read();
    			t[N + x - 1] += k;
    			if (x ^ y) {
    				t[N + y - 1] += k;
    			}
    			for (int l = N + x - 1, r = N + y - 1, lcnt = 1, rcnt = 1, cnt = 1; l ^ 1; l >>= 1, r >>= 1, cnt <<= 1) {
    				if (l ^ r && l ^ r ^ 1) {
    					if (~l & 1) {
    						t[l ^ 1] += k;
    						lcnt += cnt;
    					}
    					if (r & 1) {
    						t[r ^ 1] += k;
    						rcnt += cnt;
    					}
    					s[l >> 1] += (LL)k * lcnt;
    					s[r >> 1] += (LL)k * rcnt;
    				} else {
    					s[l >> 1] += (LL)k * (y - x + 1);
    				}
    			}
    		} else {
    			if (x ^ y) ans = s[N + x - 1] + s[N + y - 1] + t[N + x - 1] + t[N + y - 1];
    			else ans = s[N + x - 1] + t[N + x - 1];
    			for (int l = N + x - 1, r = N + y - 1, lcnt = 1, rcnt = 1, cnt = 1; l ^ 1; l >>= 1, r >>= 1, cnt <<= 1) {
    				if (l ^ r && l ^ r ^ 1) {
    					if (~l & 1) {
    						ans += s[l ^ 1] + t[l ^ 1] * cnt;
    						lcnt += cnt;
    					}
    					if (r & 1) {
    						ans += s[r ^ 1] + t[r ^ 1] * cnt;
    						rcnt += cnt;
    					}
    					ans += t[l >> 1] * lcnt + t[r >> 1] * rcnt;
    				} else {
    					ans += t[l >> 1] * (y - x + 1);
    				}
    			}
    			printf("%lld
    ", ans);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    PAT 甲级 1132 Cut Integer (20 分)
    AcWing 7.混合背包问题
    AcWing 9. 分组背包问题
    AcWing 5. 多重背包问题 II
    AcWing 3. 完全背包问题
    AcWing 4. 多重背包问题
    AcWing 2. 01背包问题
    AcWing 875. 快速幂
    AcWing 874. 筛法求欧拉函数
    AcWing 873. 欧拉函数
  • 原文地址:https://www.cnblogs.com/kcn999/p/13762420.html
Copyright © 2011-2022 走看看