模板三连击:树状数组+线段树+主席树
没事儿干,复习模板......
1.树状数组
本来不想写这个的,但是反正就几分钟就打完了,所以就写了,水AC数。
洛谷 P3374 [模板]树状数组 1
1 #include<cstdio> 2 3 typedef long long ll; 4 int n,m; 5 ll c[500005]; 6 7 int lb(int p) 8 { 9 return p&(-p); 10 } 11 12 void add(int p,int v) 13 { 14 for(int i=p;i<=n;i+=lb(i))c[i]+=(ll)v; 15 } 16 17 ll sum(int p) 18 { 19 ll ret=0; 20 for(int i=p;i;i-=lb(i))ret+=c[i]; 21 return ret; 22 } 23 24 int main() 25 { 26 scanf("%d%d",&n,&m); 27 for(int i=1;i<=n;i++) 28 { 29 int t; 30 scanf("%d",&t); 31 add(i,t); 32 } 33 for(int i=1;i<=m;i++) 34 { 35 int op,a,b; 36 scanf("%d%d%d",&op,&a,&b); 37 if(op==1)add(a,b); 38 if(op==2)printf("%lld\n",sum(b)-sum(a-1)); 39 } 40 return 0; 41 }
树状数组
2.线段树
写个既有加法又有乘法的,怕忘了。
洛谷 P3373 [模板]线段树 2
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 typedef long long ll; 6 7 int n,m,mod; 8 int lb[400005],rb[400005]; 9 ll sum[400005],lza[400005],lzm[400005]; 10 int bv[100005]; 11 12 ll sz(int p) 13 { 14 return (ll)(rb[p]-lb[p]+1); 15 } 16 17 void pushup(int p) 18 { 19 sum[p]=(sum[p<<1]+sum[p<<1|1])%mod; 20 } 21 22 void build(int p,int l,int r) 23 { 24 lb[p]=l;rb[p]=r; 25 lza[p]=0;lzm[p]=1; 26 if(l==r) 27 { 28 sum[p]=(ll)bv[l]; 29 return; 30 } 31 int mid=(l+r)>>1; 32 build(p<<1,l,mid); 33 build(p<<1|1,mid+1,r); 34 pushup(p); 35 } 36 37 void pushdown(int p) 38 { 39 if(lza[p]==0&&lzm[p]==1)return; 40 sum[p<<1]=(sum[p<<1]*lzm[p]%mod+lza[p]*sz(p<<1)%mod)%mod; 41 sum[p<<1|1]=(sum[p<<1|1]*lzm[p]%mod+lza[p]*sz(p<<1|1)%mod)%mod; 42 lzm[p<<1]=lzm[p<<1]*lzm[p]%mod; 43 lzm[p<<1|1]=lzm[p<<1|1]*lzm[p]%mod; 44 lza[p<<1]=(lza[p<<1]*lzm[p]%mod+lza[p])%mod; 45 lza[p<<1|1]=(lza[p<<1|1]*lzm[p]%mod+lza[p])%mod; 46 lza[p]=0;lzm[p]=1; 47 } 48 49 void add(int p,int l,int r,int v) 50 { 51 if(lb[p]>=l&&rb[p]<=r) 52 { 53 sum[p]=(sum[p]+(sz(p)*(ll)v)%mod)%mod; 54 lza[p]=(lza[p]+v)%mod; 55 return; 56 } 57 pushdown(p); 58 int mid=(lb[p]+rb[p])>>1; 59 if(l<=mid)add(p<<1,l,r,v); 60 if(r>mid)add(p<<1|1,l,r,v); 61 pushup(p); 62 } 63 64 void mul(int p,int l,int r,int v) 65 { 66 if(lb[p]>=l&&rb[p]<=r) 67 { 68 sum[p]=sum[p]*(ll)v%mod; 69 lzm[p]=lzm[p]*(ll)v%mod; 70 lza[p]=lza[p]*(ll)v%mod; 71 return; 72 } 73 pushdown(p); 74 int mid=(lb[p]+rb[p])>>1; 75 if(l<=mid)mul(p<<1,l,r,v); 76 if(r>mid)mul(p<<1|1,l,r,v); 77 pushup(p); 78 } 79 80 ll query(int p,int l,int r) 81 { 82 if(lb[p]>=l&&rb[p]<=r)return sum[p]; 83 pushdown(p); 84 int mid=(lb[p]+rb[p])>>1; 85 ll ret=0; 86 if(l<=mid)ret+=query(p<<1,l,r); 87 if(r>mid)ret+=query(p<<1|1,l,r); 88 return ret%mod; 89 } 90 91 int main() 92 { 93 scanf("%d%d%d",&n,&m,&mod); 94 for(int i=1;i<=n;i++)scanf("%d",&bv[i]); 95 build(1,1,n); 96 for(int i=1;i<=m;i++) 97 { 98 int op; 99 scanf("%d",&op); 100 if(op==1) 101 { 102 int x,y,k; 103 scanf("%d%d%d",&x,&y,&k); 104 mul(1,x,y,k); 105 } 106 if(op==2) 107 { 108 int x,y,k; 109 scanf("%d%d%d",&x,&y,&k); 110 add(1,x,y,k); 111 } 112 if(op==3) 113 { 114 int x,y; 115 scanf("%d%d",&x,&y); 116 ll ans=query(1,x,y); 117 printf("%lld\n",ans); 118 } 119 } 120 return 0; 121 }
线段树
还有一道题跟这个几乎一模一样,只是需要先读入初始数组再读入操作数。
传送门在下面:
洛谷 P2023 [AHOI2009]维护序列
3.主席树
洛谷 P3834 [模板]可持久化线段树 1(主席树)
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 6 int n,m; 7 int rt[200005]; 8 int sum[4000005]; 9 int ls[4000005],rs[4000005],cnt; 10 int tv[200005]; 11 12 struct data 13 { 14 int rw,w,id; 15 }a[200005]; 16 17 int cmp(data q,data w) 18 { 19 return q.rw<w.rw; 20 } 21 22 int cmpb(data q,data w) 23 { 24 return q.id<w.id; 25 } 26 27 void edit(int &p,int bef,int l,int r,int v) 28 { 29 p=++cnt; 30 sum[p]=sum[bef]+1; 31 if(l==r)return; 32 ls[p]=ls[bef];rs[p]=rs[bef]; 33 int mid=(l+r)>>1; 34 if(v<=mid)edit(ls[p],ls[bef],l,mid,v); 35 else edit(rs[p],rs[bef],mid+1,r,v); 36 } 37 38 int ask(int pl,int pr,int l,int r,int rk) 39 { 40 if(l==r)return l; 41 int mid=(l+r)>>1; 42 int sz=sum[ls[pr]]-sum[ls[pl]]; 43 if(sz>=rk)return ask(ls[pl],ls[pr],l,mid,rk); 44 else return ask(rs[pl],rs[pr],mid+1,r,rk-sz); 45 } 46 47 int main() 48 { 49 scanf("%d%d",&n,&m); 50 for(int i=1;i<=n;i++)scanf("%d",&a[i].rw),a[i].id=i; 51 sort(a+1,a+n+1,cmp); 52 a[0].rw=-0x3f3f3f3f; 53 for(int i=1;i<=n;i++) 54 { 55 if(a[i].rw==a[i-1].rw)a[i].w=a[i-1].w; 56 else a[i].w=a[i-1].w+1,tv[a[i].w]=a[i].rw; 57 } 58 sort(a+1,a+n+1,cmpb); 59 for(int i=1;i<=n;i++)edit(rt[i],rt[i-1],1,n,a[i].w); 60 for(int i=1;i<=m;i++) 61 { 62 int l,r,k; 63 scanf("%d%d%d",&l,&r,&k); 64 int ans=ask(rt[l-1],rt[r],1,n,k); 65 printf("%d\n",tv[ans]); 66 } 67 return 0; 68 }
主席树
离散化的时候,忘把 a[0].rw 赋成-0x3f3f3f3f了,导致WA声一片......
转载于:https://www.cnblogs.com/eternhope/p/9917103.html
模板三连击:树状数组+线段树+主席树相关推荐
- D-query SPOJ - DQUERY(求区间不同数的个数)(树状数组||线段树+离散)(主席树+在线)
English Vietnamese Given a sequence of n numbers a1, a2, -, an and a number of d-queries. A d-query ...
- HDU 4325 离散化+树状数组 或者 不使用树状数组
题意:给出一些花的开放时间段,然后询问某个时间点有几朵花正在开放. 由于ti<1e9,我们需要先将时间离散化,然后将时间点抽象为一个数组中的点,显然,我们需要进行区间更新和单点查询,可以考虑线段 ...
- HDU 1556 前缀和 树状数组 线段树
解法一: a[i]表示以 i作为起点,对 i-n的气球全部上色的次数 对(start,end)区间上色 ++a[start] --a[end+1]抵消掉 end+1-n的部分 问题转换为求 a的前缀 ...
- jzoj3854-分组【树状数组,线段树】
正题 题目链接:https://jzoj.net/senior/#contest/show/2990/2 题目大意 一个小队满足要求 队长的地位最高 所有队员和队长的年龄差不超过kkk 给出nnn个人 ...
- 51nod 1680区间求和 (dp+树状数组/线段树)
不妨考虑已知一个区间[l,r]的k=1.k=2....k=r-l+1这些数的答案ans(只是这一个区间,不包含子区间) 那么如果加入一个新的数字a[i](i = r+1) 则新区间[l, i]的答案为 ...
- CCF201709-5 除法(100分)【树状数组+线段树】
试题编号: 201709-5 试题名称: 除法 时间限制: 10.0s 内存限制: 256.0MB 问题描述: 问题描述 小葱喜欢除法,所以他给了你N个数a1, a2, ⋯, aN,并且希望你执行M次 ...
- POJ2182 HDU2711 Lost Cows【树状数组+线段树】
Lost Cows Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 17113 Accepted: 10664 Descripti ...
- P2357 守墓人(树状数组/线段树)
题目描述 在一个荒凉的墓地上 有一个令人尊敬的守墓人, 他看守的墓地从来 没有被盗过, 所以人们很放心的把自己的先人的墓 安顿在他那 守墓人能看好这片墓地是必然而不是偶然..... 因为....守墓人 ...
- 差分+树状数组 线段树【P2357】 守墓人
题目描述-->p2357 守墓人 敲了一遍线段树,水过. 树状数组分析 主要思路: 差分 简单介绍一下差分(详细概念太麻烦,看下面. 给定一个数组 7 8 6 5 1 8 18 20 35 // ...
最新文章
- Lua 性能相关笔记
- 【Android 逆向】Android 逆向通用工具开发 ( 静态库项目中的网络操作核心类 CNetwork 分析 )
- 计算char,short,int,long类型变量的取值范围
- python3 携程_多任务(3):协程
- 美国全国步枪协会遭 Grief 勒索软件攻击
- python workflow_用 Python 写 Alfred3 workflow 插件,一个最小示例
- Python全栈开发【基础-11】基本数据类型内置方法
- python点云数据处理_python处理点云数据并生成三维点云模型
- STM32F429+W25Q256+TouchFGX
- 【2018.12.28】百度网盘永久保存2T容量办法
- M个苹果放在N个盘子里,有多少种不同的放法
- Thinkpad T410加内存
- 迅雷android 电视,【迅雷电视助手】迅雷电视助手安卓版(Android)2.0下载_太平洋下载中心...
- 在Linux系统下制作U盘启动盘
- 微信小程序——生命周期
- AR红包Android端实现原理
- java 字符串掐头去尾_java中常见的类
- Apache POI 合并单元格
- Program received signal SIGSEGV, Segmentation fault.
- 老站长揭秘Google Adsense盈利的真相(2021版)
热门文章
- Linux下安装配置vsftpd
- Installation error: INSTALL_FAILED_NO_MATCHING_ABIS
- C语言实现的RSA算法程序
- 20135316王剑桥 linux第六周课实验笔记
- 如果安装License失败的解决方案
- @Controller 不能访问到
- 计算机辅助开始于计算机发展的第几个阶段,计算机辅助开始于计算机发展第几阶段...
- ubuntu 发数据给usb_【奇怪的知识】USB 镜像刻录知识点
- java并发编程之Thread.sleep方法详解
- PostgreSQL查看系统视图的源码