没事儿干,复习模板......

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

模板三连击:树状数组+线段树+主席树相关推荐

  1. D-query SPOJ - DQUERY(求区间不同数的个数)(树状数组||线段树+离散)(主席树+在线)

    English Vietnamese Given a sequence of n numbers a1, a2, -, an and a number of d-queries. A d-query ...

  2. HDU 4325 离散化+树状数组 或者 不使用树状数组

    题意:给出一些花的开放时间段,然后询问某个时间点有几朵花正在开放. 由于ti<1e9,我们需要先将时间离散化,然后将时间点抽象为一个数组中的点,显然,我们需要进行区间更新和单点查询,可以考虑线段 ...

  3. HDU 1556 前缀和 树状数组 线段树

    解法一: a[i]表示以 i作为起点,对 i-n的气球全部上色的次数  对(start,end)区间上色 ++a[start] --a[end+1]抵消掉 end+1-n的部分 问题转换为求 a的前缀 ...

  4. jzoj3854-分组【树状数组,线段树】

    正题 题目链接:https://jzoj.net/senior/#contest/show/2990/2 题目大意 一个小队满足要求 队长的地位最高 所有队员和队长的年龄差不超过kkk 给出nnn个人 ...

  5. 51nod 1680区间求和 (dp+树状数组/线段树)

    不妨考虑已知一个区间[l,r]的k=1.k=2....k=r-l+1这些数的答案ans(只是这一个区间,不包含子区间) 那么如果加入一个新的数字a[i](i = r+1) 则新区间[l, i]的答案为 ...

  6. CCF201709-5 除法(100分)【树状数组+线段树】

    试题编号: 201709-5 试题名称: 除法 时间限制: 10.0s 内存限制: 256.0MB 问题描述: 问题描述 小葱喜欢除法,所以他给了你N个数a1, a2, ⋯, aN,并且希望你执行M次 ...

  7. POJ2182 HDU2711 Lost Cows【树状数组+线段树】

    Lost Cows Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 17113 Accepted: 10664 Descripti ...

  8. P2357 守墓人(树状数组/线段树)

    题目描述 在一个荒凉的墓地上 有一个令人尊敬的守墓人, 他看守的墓地从来 没有被盗过, 所以人们很放心的把自己的先人的墓 安顿在他那 守墓人能看好这片墓地是必然而不是偶然..... 因为....守墓人 ...

  9. 差分+树状数组 线段树【P2357】 守墓人

    题目描述-->p2357 守墓人 敲了一遍线段树,水过. 树状数组分析 主要思路: 差分 简单介绍一下差分(详细概念太麻烦,看下面. 给定一个数组 7 8 6 5 1 8 18 20 35 // ...

最新文章

  1. Lua 性能相关笔记
  2. 【Android 逆向】Android 逆向通用工具开发 ( 静态库项目中的网络操作核心类 CNetwork 分析 )
  3. 计算char,short,int,long类型变量的取值范围
  4. python3 携程_多任务(3):协程
  5. 美国全国步枪协会遭 Grief 勒索软件攻击
  6. python workflow_用 Python 写 Alfred3 workflow 插件,一个最小示例
  7. Python全栈开发【基础-11】基本数据类型内置方法
  8. python点云数据处理_python处理点云数据并生成三维点云模型
  9. STM32F429+W25Q256+TouchFGX
  10. 【2018.12.28】百度网盘永久保存2T容量办法
  11. M个苹果放在N个盘子里,有多少种不同的放法
  12. Thinkpad T410加内存
  13. 迅雷android 电视,【迅雷电视助手】迅雷电视助手安卓版(Android)2.0下载_太平洋下载中心...
  14. 在Linux系统下制作U盘启动盘
  15. 微信小程序——生命周期
  16. AR红包Android端实现原理
  17. java 字符串掐头去尾_java中常见的类
  18. Apache POI 合并单元格
  19. Program received signal SIGSEGV, Segmentation fault.
  20. 老站长揭秘Google Adsense盈利的真相(2021版)

热门文章

  1. Linux下安装配置vsftpd
  2. Installation error: INSTALL_FAILED_NO_MATCHING_ABIS
  3. C语言实现的RSA算法程序
  4. 20135316王剑桥 linux第六周课实验笔记
  5. 如果安装License失败的解决方案
  6. @Controller 不能访问到
  7. 计算机辅助开始于计算机发展的第几个阶段,计算机辅助开始于计算机发展第几阶段...
  8. ubuntu 发数据给usb_【奇怪的知识】USB 镜像刻录知识点
  9. java并发编程之Thread.sleep方法详解
  10. PostgreSQL查看系统视图的源码