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;
    }
    
  • 相关阅读:
    第九章、查找
    opencv- python使用
    opencv初入
    初入
    第四章、数学问题
    数据结构
    分享一个SQLSERVER脚本
    详解SQL语句的集合运算
    数据库权限分配探讨
    数据库分区分表以及读写分离
  • 原文地址:https://www.cnblogs.com/kcn999/p/13762420.html
Copyright © 2011-2022 走看看