NotOnlySuccess大神的飘逸版线段树
来源:互联网 发布:制作简谱软件下载 编辑:程序博客网 时间:2024/04/29 17:05
吐槽:在模板题,我的丑陋的线段树跑了984ms,而大神的只跑了364ms,看来我的代码还是太丑了QAQ
大神的线段树也没什么大优化,就是不知道为什么超级快,或许是我以前看的线段树代码不好吧。。。
我推荐这个线段树的主要原因就是非常好写,空间也是非常小,思路极其清晰。
好了,废话不多说,直接上代码:
#include<bits/stdc++.h>#define ll long longusing namespace std;const int maxn=100001;ll sum[maxn<<2];ll add[maxn<<2];inline void pushup(int rt){ sum[rt]=sum[rt<<1]+sum[rt<<1|1];}void build(int l,int r,int rt){ if(l==r){ scanf("%lld",&sum[rt]); return; } int mid=(l+r)>>1; build(l,mid,rt<<1); build(mid+1,r,rt<<1|1); pushup(rt);}inline void pushdown(int rt,int len){ if(add[rt]){ add[rt<<1]+=add[rt]; add[rt<<1|1]+=add[rt]; sum[rt<<1]+=add[rt]*(len-(len>>1)); sum[rt<<1|1]+=add[rt]*(len>>1); add[rt]=0; }}void update(int L,int R,int c,int l,int r,int rt){ if(L<=l&&r<=R){ add[rt]+=c; sum[rt]+=c*(r-l+1); return; } pushdown(rt,r-l+1); int mid=(l+r)>>1; if(L<=mid)update(L,R,c,l,mid,rt<<1); if(mid+1<=R)update(L,R,c,mid+1,r,rt<<1|1); pushup(rt);}ll query(int L,int R,int l,int r,int rt){ if(L<=l&&r<=R){ return sum[rt]; } pushdown(rt,r-l+1); ll ans=0; int mid=(l+r)>>1; if(L<=mid)ans+=query(L,R,l,mid,rt<<1); if(mid+1<=R)ans+=query(L,R,mid+1,r,rt<<1|1); return ans;}int main(){ int n,m; scanf("%d %d",&n,&m); build(1,n,1); for(int i=1;i<=m;i++){ int g; scanf("%d",&g); if(g&1){ int l,r; ll c; scanf("%d %d %lld",&l,&r,&c); update(l,r,c,1,n,1); } else{ int l,r; scanf("%d %d",&l,&r); printf("%lld\n",query(l,r,1,n,1)); } } return 0;}
以上是区间加+区间和
下面是区间加+区间乘+区间和:(这代码好难调啊)
#include<bits/stdc++.h>#define ll long longusing namespace std;const int maxn=100001;ll p;ll sum[maxn<<2];ll add[maxn<<2];ll mul[maxn<<2];inline void pushup(int rt){ sum[rt]=(sum[rt<<1]+sum[rt<<1|1])%p;}inline void mark(int l,int r,int rt,ll a,ll b){ sum[rt]=(sum[rt]*a+(r-l+1)*b)%p; mul[rt]=(mul[rt]*a)%p; add[rt]=(add[rt]*a+b)%p;}inline void pushdown(int l,int r,int rt){ if(mul[rt]!=1||add[rt]!=0){ int mid=(l+r)>>1; mark(l,mid,rt<<1,mul[rt],add[rt]); mark(mid+1,r,rt<<1|1,mul[rt],add[rt]); add[rt]=0; mul[rt]=1; }}void build(int l,int r,int rt){ mul[rt]=1; if(l==r){ scanf("%lld",&sum[rt]); return; } int mid=(l+r)>>1; build(l,mid,rt<<1); build(mid+1,r,rt<<1|1); pushup(rt);}void update(int L,int R,int l,int r,int rt,ll a,ll b){ if(L<=l&&r<=R){ mark(l,r,rt,a,b); return; } pushdown(l,r,rt); int mid=(l+r)>>1; if(L<=mid)update(L,R,l,mid,rt<<1,a,b); if(mid+1<=R)update(L,R,mid+1,r,rt<<1|1,a,b); pushup(rt);}ll query(int L,int R,int l,int r,int rt){ if(L<=l&&r<=R){ return sum[rt]%p; } pushdown(l,r,rt); ll ans=0; int mid=(l+r)>>1; if(L<=mid)ans+=query(L,R,l,mid,rt<<1); if(mid+1<=R)ans+=query(L,R,mid+1,r,rt<<1|1); return ans%p;}int main(){ int n,m; scanf("%d %d %lld",&n,&m,&p); build(1,n,1); for(int i=1;i<=m;i++){ int g; scanf("%d",&g); if(g==1){ int l,r; ll c; scanf("%d %d %lld",&l,&r,&c); update(l,r,1,n,1,c,0); } else if(g==2){ int l,r; ll c; scanf("%d %d %lld",&l,&r,&c); update(l,r,1,n,1,1,c); } else{ int l,r; scanf("%d %d",&l,&r); printf("%lld\n",query(l,r,1,n,1)); } } return 0;}
end
阅读全文
1 0
- NotOnlySuccess大神的飘逸版线段树
- notonlysuccess大神的线段树完全版
- NotOnlySuccess 的【完全版】线段树
- 《完全版线段树》- NotOnlySuccess
- 《完全版线段树》- NotOnlySuccess
- 转载notonlysuccess的线段树博客
- 【完全版】线段树(转载notonlysuccess)
- 《完全版线段树》——notonlysuccess
- Notonlysuccess 线段树
- notonlysuccess 线段树 高人推荐
- notonlysuccess 线段树 高人推荐
- NotOnlySuccess 大牛的线段树的题目
- 线段树——Powered By NotOnlySuccess
- 线段树模板(NOTONLYSUCCESS神牛)
- 【完整版】线段树(转载 NotOnlySuccess)
- 线段树——Powered By NotOnlySuccess
- 线段树 (矩形面积并&&周长并 - 来自notonlysuccess)
- 飘逸的python - 实现trie树
- JavaScript的记忆函数真的可以提升性能吗?
- Solaris系统cron服务异常解决记录
- 大小端个人理解
- 『Python』关于Pandas的一点用法
- Transform组件
- NotOnlySuccess大神的飘逸版线段树
- js学习(16)----函数声明和函数作为参数
- JSP内置对象
- 排序算法
- 【网络流24题】太空飞行计划(最大权闭合图+最小割)
- org.apache.hadoop.hbase.PleaseHoldException: Master is initializing解决方案
- Android中SQLite应用详解
- 最小生成树
- 将form表单中的值序列化成对象