补个线段树

区间操作与查询线段树
本文介绍了一种使用线段树进行区间加法、乘法及查询的应用案例,通过定义节点属性并采用懒标记的方式优化操作效率。适用于解决区间更新与查询的问题。
  1 #include<cstdio> 
  2 #include<cstring>
  3 #include<cmath>
  4 #include<ctime>
  5 #include<iostream>
  6 #include<algorithm>
  7 #include<queue>
  8 #include<set>
  9 #define inf (0x7fffffff)
 10 #define l(a) ((a)<<1)
 11 #define r(a) ((a)<<1|1)
 12 #define b(a) (1<<(a))
 13 #define rep(i,a,b) for(int i=a;i<=(b);i++)
 14 #define clr(a) memset(a,0,sizeof(a))
 15 typedef long long ll;
 16 typedef unsigned long long ull;
 17 using namespace std;
 18 int readint(){
 19     int t=0,f=1;char c=getchar();
 20     while(!isdigit(c)){
 21         if(c=='-') f=-1;
 22         c=getchar();
 23     }
 24     while(isdigit(c)){
 25         t=(t<<3)+(t<<1)+c-'0';
 26         c=getchar();
 27     }
 28     return t*f;
 29 }
 30 const int maxn=100009;
 31 struct node{
 32     int l,r;
 33     ll s,a,m;
 34 }x[maxn<<2];
 35 int n,m;
 36 ll mod;
 37 void maintain(int t){
 38     x[t].s=(x[l(t)].s+x[r(t)].s)%mod;
 39 }
 40 void pushdown(int t){
 41     if(x[t].l==x[t].r){
 42         x[t].a=0;x[t].m=1;return;
 43     }
 44     if(x[t].m!=1){
 45         x[l(t)].s=x[l(t)].s*x[t].m%mod;
 46         x[r(t)].s=x[r(t)].s*x[t].m%mod;
 47         x[l(t)].m=x[l(t)].m*x[t].m%mod;x[r(t)].m=x[r(t)].m*x[t].m%mod;
 48         x[l(t)].a=x[l(t)].a*x[t].m%mod;x[r(t)].a=x[r(t)].a*x[t].m%mod;
 49         x[t].m=1;
 50     }
 51     if(x[t].a){
 52         x[l(t)].s=(x[l(t)].s+(x[l(t)].r-x[l(t)].l+1)*x[t].a)%mod;
 53         x[r(t)].s=(x[r(t)].s+(x[r(t)].r-x[r(t)].l+1)*x[t].a)%mod;
 54         x[l(t)].a=(x[l(t)].a+x[t].a)%mod;x[r(t)].a=(x[r(t)].a+x[t].a)%mod;
 55         x[t].a=0;
 56     }    
 57 }
 58 ll del;
 59 void add(int t,int l,int r){
 60     pushdown(t);
 61     if(x[t].l==l&&x[t].r==r){
 62         x[t].s=(x[t].s+(x[t].r-x[t].l+1)*del)%mod;
 63         x[t].a=(x[t].a+del)%mod;
 64         return;
 65     }
 66     int mid=(x[t].l+x[t].r)>>1;
 67     if(l>mid) add(r(t),l,r);
 68     else if(r<=mid) add(l(t),l,r);
 69     else{
 70         add(l(t),l,mid);
 71         add(r(t),mid+1,r);
 72     }
 73     maintain(t);
 74 }
 75 void mul(int t,int l,int r){
 76     pushdown(t);
 77     if(x[t].l==l&&x[t].r==r){
 78         x[t].s=(x[t].s*del)%mod;
 79         x[t].m=x[t].m*del%mod;
 80         x[t].a=x[t].a*del%mod;
 81         return;
 82     }
 83     int mid=(x[t].l+x[t].r)>>1;
 84     if(l>mid) mul(r(t),l,r);
 85     else if(r<=mid) mul(l(t),l,r);
 86     else{
 87         mul(l(t),l,mid);
 88         mul(r(t),mid+1,r);
 89     }
 90     maintain(t);
 91 }
 92 ll qury(int t,int l,int r){
 93     pushdown(t);
 94     if(x[t].l==l&&x[t].r==r) return x[t].s;
 95     int mid=(x[t].l+x[t].r)>>1;
 96     if(l>mid) return qury(r(t),l,r)%mod;
 97     if(r<=mid) return qury(l(t),l,r)%mod;
 98     return (qury(l(t),l,mid)%mod+qury(r(t),mid+1,r)%mod)%mod;
 99 }
100 void build(int t,int l,int r){
101     x[t].l=l;x[t].r=r;x[t].m=1;
102     if(l==r){
103         x[t].s=readint()%mod;
104         return;
105     }
106     int mid=(l+r)>>1;
107     build(l(t),l,mid);
108     build(r(t),mid+1,r);
109     maintain(t);
110 }
111 int main(){
112     //freopen("#input.txt","r",stdin);
113     //freopen("#output.txt","w",stdout);
114     n=readint();m=readint();mod=readint();
115     build(1,1,n);
116     while(m--){
117         int opt=readint(),L=readint(),R=readint();
118         if(opt==3) printf("%lld\n",(qury(1,L,R)+mod)%mod);
119         else{
120             del=readint()%mod;
121             if(opt==2) add(1,L,R);
122             else mul(1,L,R);
123         }
124     }
125     //fclose(stdin);
126     //fclose(stdout);
127     return 0;
128 }
View Code

 

转载于:https://www.cnblogs.com/chensiang/p/8051649.html

内容概要:本文详细介绍了“秒杀商城”微服务架构的设计与实战过程,涵盖系统从需求分析、服务拆分、技术选型到核心功能开发、分布式事务处理、容器化部署及监控链路追踪的完整流程。重点解决了高并发场景下的超卖问题,采用Redis预减库存、消息队列削峰、数据库乐观锁等手段保障数据一致性,并通过Nacos实服务注册发与配置管理,利用Seata处理跨服务分布式事务,结合RabbitMQ实异步下单,提升系统吞吐能力。同时,项目支持Docker Compose快速部署和Kubernetes生产级编排,集成Sleuth+Zipkin链路追踪与Prometheus+Grafana监控体系,构建可观测性强的微服务系统。; 适合人群:具备Java基础和Spring Boot开发经验,熟悉微服务基本概念的中高级研发人员,尤其是希望深入理解高并发系统设计、分布式事务、服务治理等核心技术的开发者;适合工作2-5年、有志于转型微服务或提升架构能力的工程师; 使用场景及目标:①学习如何基于Spring Cloud Alibaba构建完整的微服务项目;②掌握秒杀场景下高并发、超卖控制、异步化、削峰填谷等关键技术方案;③实践分布式事务(Seata)、服务熔断降级、链路追踪、统一配置中心等企业级中间件的应用;④完成从本地开发到容器化部署的流程落地; 阅读建议:建议按照文档提供的七个阶段循序渐进地动手实践,重点关注秒杀流程设计、服务间通信机制、分布式事务实和系统性能优化部分,结合代码调试与监控工具深入理解各组件协作原理,真正掌握高并发微服务系统的构建能力。
<think>嗯,用户问的是ZWK线段树,我得先回忆一下相关的知识。ZWK线段树,也叫张昆玮线段树,是线段树的一种非递归实方法。对吧?我记得传统的线段树是递归实的,而ZWK线段树用非递归的方式优化了常数,可能更适合某些场合。 首先,我得确定自己对这个结构的理解是否正确。ZWK线段树的特点包括非递归、自底向上、位运算优化,这些是不是关键点?对的,比如它通过位运算快速定位叶子节点,省去了递归的开销,所以速度更快,尤其是在区间更新和查询时。 然后,需要整理它的实步骤。例如,构建的时候需要找到第一个叶子节点的位置,通常取大于等于n的最小2的幂次,比如n=5的话,就是8。然后初始化叶子节点,再自底向上合并父节点。这部分要详细说明,用户可能需要具体的步骤来理解如何构建。 接下来是查询和更新操作。查询区间的时候,ZWK线段树采用左右指针分别处理,逐步移动到父节点,直到覆盖整个区间。而更新操作则是找到叶子节点后自底向上更新父节点。这里需要注意,区间操作可能需要标记下传,但ZWK线段树通常用于不需要延迟标记的情况,或者需要特殊处理延迟标记,这也是它的一个局限性。 然后,要总结它的优缺点。优点当然是高效,非递归省时间,适合卡常数的题目。缺点可能是不支持复杂的延迟标记,结构固定,扩展性差,内存占用较大,特别是当n不是2的幂时会有空间浪费。 用户可能想知道适用场景,比如频繁的区间查询和单点更新,或者对效率要求高的场合。但如果是需要复杂标记的区间更新,可能不太适合。 还要考虑用户可能的疑问,比如和普通线段树的区别,为什么非递归更快,是否容易实等。需要解释清楚非递归避免了函数调用开销,位运算快速计算位置,所以常数小。 可能用户在学习线段树时遇到了效率问题,或者听说ZWK线段树更高效,想了解如何应用。需要给出例子,比如区间求和的实步骤,这样用户能更直观地理解。 最后,要确保回答结构清晰,分点说明,帮助用户逐步理解。检查是否遵循了系统指令,数学公式是否正确使用$...$和$$...$$,语言用中文,没有语法错误。可能需要举一个例子来说明构建和查询过程,但注意不要太复杂,以免让用户更困惑。 在整理一下思路,先介绍ZWK线段树是什么,然后特点,实步骤,操作,优缺点,适用场景,最后一个小例子。确保每个部分简明扼要,符合用户的需求。</think>好的,我将逐步介绍ZWK线段树的核心概念和实原理。 --- ### 1. **ZWK线段树是什么?** ZWK线段树(又称**张昆玮线段树**)是线段树的一种**非递归实**,由中国选手张昆玮(ID: zkw)提出。它通过**位运算优化**和**自底向上**的更新方式,显著降低了常数,在算法竞赛中常用于高效处理区间查询和更新问题。 --- ### 2. **核心特点** - **非递归实**:避免函数调用开销,运行更快。 - **自底向上操作**:从叶子节点开始处理,逐步合并到根节点。 - **位运算优化**:利用二进制技巧快速定位节点。 - **适合单点/区间操作**:如求和、最值等。 --- ### 3. **实步骤** #### (1) **初始化:构建满二叉树** - 将原数据填充到叶子节点,并扩展长度到$2^m$(满足$2^m \ge n$的最小值)。 - **示例**:$n=5$时,需扩展为$m=3$(即长度$8$)。 #### (2) **构建树结构** - **叶子节点**:直接存储数据,位置为$[2^m, 2^{m+1}-1]$。 - **非叶子节点**:自底向上合并子节点信息。 $$ \text{父节点值} = \text{左子节点值} + \text{右子节点值} $$ #### (3) **查询与更新** - **单点更新**:找到叶子节点,自底向上更新父节点。 - **区间查询**:通过左右指针逐步合并区间结果。 --- ### 4. **关键操作详解** #### (1) **单点更新** ```python def update(pos, value): pos += base # 定位到叶子节点 tree[pos] = value while pos > 1: pos >>= 1 # 移动到父节点 tree[pos] = tree[pos*2] + tree[pos*2+1] ``` #### (2) **区间查询** ```python def query(l, r): res = 0 l += base - 1 # 左闭 r += base + 1 # 右开 while (l ^ r ^ 1): # 判断是否在同一层 if ~l & 1: res += tree[l^1] # 左指针向右合并 if r & 1: res += tree[r^1] # 右指针向左合并 l >>= 1; r >>= 1 return res ``` --- ### 5. **优缺点分析** | **优点** | **缺点** | |------------------------------|------------------------------| | 常数小,适合卡常题 | 不支持复杂延迟标记(如区间乘)| | 代码简洁,无需递归 | 需预先分配$2^{m+1}$空间 | | 单点/区间操作效率高 | 对非满二叉树场景不友好 | --- ### 6. **适用场景** - 频繁的**单点更新+区间查询**(如求区间和、最值)。 - 对运行速度要求高的题目(如$10^6$次操作)。 - **不适用**:需要复杂延迟标记的区间修改(如区间加+区间乘混合操作)。 --- ### 7. **简单示例** 假设数组为$[1,3,5,7,9]$,扩展为长度$8$: - **叶子节点**:$[0,0,0,0,1,3,5,7,9]$(前0到长度$8$) - **构建后树结构**: $$ \begin{aligned} &\text{根节点: } 25 \\ &\text{第二层: } 4 \quad 21 \\ &\text{叶子层: } 0 \quad 0 \quad 1 \quad 3 \quad 5 \quad 7 \quad 9 \quad 0 \\ \end{aligned} $$ --- ### 8. **总结** ZWK线段树通过**非递归+位运算优化**,在特定场景下性能显著优于递归线段树,但灵活性较低。掌握其核心思想后,可根据题目需求选择合适的数据结构。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值