博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
线段树复合标记
阅读量:6245 次
发布时间:2019-06-22

本文共 3740 字,大约阅读时间需要 12 分钟。

#include
#include
#include
#include
int a[100005],p;static const int MAXN=400000;struct Segment_tree///1.把一段区间变成同一个数,2求任意区间的和{ int size;///区间容量 struct Node { long long a; long long b; long long sum; int len; void fun(long long a1,long long b1)///复合一个新标记 { a=a*a1%p; b=(b*a1+b1)%p; } void use() { sum=(sum*a+b*len)%p; } void clear() { a=1; b=0; } bool islazy() { return a!=1||b!=0; } } node[MAXN]; void update(int pos)///结点更新函数 { if(pos>=size)///判断是叶子 { node[pos].sum=a[pos-size]%p; } else { node[pos].sum=(node[pos<<1].sum+node[pos<<1^1].sum)%p; node[pos].len=node[pos<<1].len+node[pos<<1^1].len; } if(node[pos].islazy())///注意如果有懒惰标记的话要把懒惰标记用掉 node[pos].use(); } void build(int n)///申请空空间 { n+=4;///保险起见,申请时,申请得稍微大一点 size=1; while(size
0; i--) { node[i].clear(); update(i);///数值更新上去 } } void putdown(int s,int t)///将标记放下 { if(s>1)///判断是否到顶,没达到顶继续往上爬 { putdown(s>>1,t>>1); } if(node[s].islazy())///判断有没有标记,如果有标记话,下放给孩子 { node[s<<1].fun(node[s].a,node[s].b); node[s<<1^1].fun(node[s].a,node[s].b); node[s].clear(); } if(node[t].islazy()) { node[t<<1].fun(node[t].a,node[t].b); node[t<<1^1].fun(node[t].a,node[t].b); node[t].clear(); } } void add(int l,int r,int x) { int s=l+size-1; int t=r+size+1; putdown(s>>1,t>>1); ///更新标记>更新值>查询查询值 for(; s^t^1; s>>=1,t>>=1) { // printf("[%d %d]\n",s,t); if(~s&1) node[s^1].fun(1,x); if(t&1) node[t^1].fun(1,x); update(s); update(t); update(s^1); update(t^1); } while(s)///一直更新到顶 { update(s); update(s^1); s>>=1; } } void mul(int l,int r,int x) { int s=l+size-1; int t=r+size+1; putdown(s>>1,t>>1); ///更新标记>更新值>查询查询值 for(; s^t^1; s>>=1,t>>=1) { // printf("[%d %d]\n",s,t); if(~s&1) node[s^1].fun(x,0); if(t&1) node[t^1].fun(x,0); update(s); update(t); update(s^1); update(t^1); } while(s)///一直更新到顶 { update(s); update(s^1); s>>=1; } } int query(int l,int r) { int s=l+size-1; int t=r+size+1; putdown(s>>1,t>>1); long long sum=0; ///更新标记>更新值>查询查询值 for(; s^t^1; s>>=1,t>>=1) { update(s); update(t); update(s^1); update(t^1); // printf("[%d %d]\n",s,t); if(~s&1) { sum+=node[s^1].sum; } if(t&1) { sum+=node[t^1].sum; } } while(s)///一直更新到顶 { update(s); update(s^1); s>>=1; } return sum%p; } void put() { int i=1,j=1,s=size*4,k,len=3; for(i=1; i<=2*size-1; i++) { if(i==j) { puts(""); j<<=1; s>>=1; for(k=0; k

 

转载于:https://www.cnblogs.com/xcantaloupe/p/6837634.html

你可能感兴趣的文章
学习笔记TF036:实现Bidirectional LSTM Classifier
查看>>
应用监控预警&服务链路跟踪-Pinpoint介绍
查看>>
前端:后端,我要分手
查看>>
smarty isset 怎样使用
查看>>
用图帮你了解https的原理
查看>>
区块链如何改变AI
查看>>
HTML5/JavaScript UI控件Wijmo Enterprise 2018v2发布
查看>>
工业仪表盘控件Iocomp ActiveX常见问题(2):Visual Basic中的错误
查看>>
Docker下使用selenium+testng实现web自动化
查看>>
当执行npm时遇到的问题
查看>>
JAVA程序员面试30问(附带答案)
查看>>
Java性能调优攻略全分享,七步搞定!(附学习资料分享)
查看>>
企业级 SpringBoot 教程 (六)springboot整合mybatis
查看>>
程序员写了一段注释, 第二天惨被公司开除, 公司巧妙回怼
查看>>
8.eclipse 安装 lombook插件
查看>>
Maven项目中使用本地JAR包方案4
查看>>
如何利用XMind创建概念图
查看>>
ldap接触(3)之LDAP特定错误以及错误一览表
查看>>
Zookeeper的功能以及工作原理
查看>>
朝花夕拾之Oracle11g 表分区
查看>>