模板

朴素树状数组:

  区间加,并不带lazy tag(lowbit()表

 1 #define MAXN 500000
 2 #include <cstdio>
 3 using namespace std;
 4 
 5 int n, m, fenwick[MAXN], a[MAXN];    //fenwick[]为树状数组,a是原始数组
 6 
 7 int lowbit(int x){return x&(-x);}    //lowbit()操作
 8 
 9 void update(int pos, int x){        //在pos处对原数字进行增量x的操作,并更新fenwick[]
10     for(int i = pos; i <= n; i += lowbit(i))
11         fenwick[i] += x;
12 }
13 
14 void print(){        //用于测试,观察fenwick[]的内容
15     printf("Fenwick array will be shown bellow:\n");
16     for(int i = 1; i < n; i++)printf("%d ", fenwick[i]);
17     printf("%d\n", fenwick[n]);
18 }
19 
20 int query(int head, int tail){
21 //查询[head, tail]的区间和,其实就是前缀和相减求和的合并版
22     int ret = 0;
23     for(int i = tail; i >= 1; i -= lowbit(i))ret += fenwick[i];
24     for(int i = head - 1; i >= 1; i -= lowbit(i))ret -= fenwick[i];
25     return ret;
26 }
27 
28 void init(){
29     int ctrl, x, y;        //ctrl为控制符,1为更新,2为查询
30     scanf("%d%d", &n, &m);
31     for(int i = 1; i <= n; i++){    //输入初始数组
32         scanf("%d", &a[i]);
33         update(i, a[i]);
34     }
35     //print();
36     for(int i = 1; i <= m; i++){
37         scanf("%d%d%d", &ctrl, &x, &y);
38         if(ctrl == 1){update(x, y);/*print();*/}
39         else printf("%d\n", query(x, y));
40     }
41 }
42 
43 int main(int argc, char const *argv[]){
44     init();
45     return 0;
46 }
47 
48 //对应洛谷模板题:https://www.luogu.org/problemnew/show/P3374
树状数组模板

 

简单并查集:

  没有套在最小生成树等算法中,只是一个简单的实现

 1 #define MAXN 100000     //并查集极限大小
 2 #include <cstdio>
 3 using namespace std;
 4 
 5 int n, m;               // n 表示并查集元素个数, m 表示操作数目( 包括合并与查询 )
 6 int num[MAXN], father[MAXN];    // num[]即为集中元素, father[]存储各元素的父亲
 7 //build()以size为大小建立并查集, 将每个元素的父亲设为自己
 8 void build(int size){for(int i = 1;i <= size; i++)father[num[i]] = num[i];}
 9 //查找元素x的祖先
10 int getFather(int x){return x == father[x] ? x : getFather(father[x]);}
11 //将a,b放入同集合, 并实现路径压缩, 直接连接祖先
12 void merge(int a, int b){father[getFather(a)] = getFather(b);}
13 //查询a与b是否在同一集合中, 通过对比祖先实现
14 bool query(int a, int b){
15     int x = getFather(a);
16     int y = getFather(b);
17     return x==y ? true : false;
18 }
19 
20 void init(){
21     scanf("%d", &n);
22     for(int i = 1; i <= n; i++){
23         scanf("%d", &num[i]);
24     }
25     build(n);
26     scanf("%d", &m);
27     for(int i = 1;i <= m;i++){
28         int ctrl, a, b;
29         scanf("%d%d%d", &ctrl, &a, &b);     //ctrl为1时合并元素, 为2时查询
30         if(ctrl==1)merge(a, b);else{
31             if(query(a, b))printf("Yes\n");
32             else printf("No\n");
33         }
34     }
35 }
36 
37 int main(int argc, char const *argv[]){
38     init();
39     return 0;
40 }
41 
42 /*
43 期望测试结果
44 5   2    4    7   6
45 1.  2 5 4 => No
46 2.  1 5 4
47 3.  2 5 4 => Yes
48 4.  2 5 2 => No
49 5.  1 2 4
50 6.  2 5 2 => Yes
51 
52 不完全对应洛谷模板题:https://www.luogu.org/problemnew/show/P3367
53 */
简单并查集

 

 哈希表:

  只是简单的数字存储(其实写的很蠢而且无甚可移植性)

 1 #define MAXN  100000
 2 #define tan90 0
 3 #include <cstdio>
 4 using namespace std;
 5 
 6 //素数表,用以产生MOD
 7 const int prime[] = {2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,
 8     101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,
 9     223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,
10     349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,
11     479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,
12     619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,
13     769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,
14     929,937,941,947,953,967,971,977,983,991,997,1009,1013,1019,1021,1031,1033,1039,1049,1051,
15     1061,1063,1069,1087,1091,1093,1097,1103,1109,1117,1123,1129,1151,1153,1163,1171,1181,1187,
16     1193,1201,1213,1217,1223,1229,1231,1237,1249,1259,1277,1279,1283,1289,1291,1297,1301,1303,
17     1307,1319,1321,1327,1361,1367,1373,1381,1399,1409,1423,1427,1429, 1433,1439,1447,1451,1453,
18     1459,1471,1481,1483,1487,1489,1493,1499,1511,1523,1531,1543,1549,1553,1559,1567,1571,1579,
19     1583,1597,1601,1607,1609,1613,1619,1621,1627,1637,1657,1663,1667,1669,1693,1697,1699,1709,
20     1721,1723,1733,1741,1747,1753,1759,1777,1783,1787,1789,1801,1811,1823,1831,1847,1861,1867,
21     1871,1873,1877,1879,1889,1901,1907,1913,1931,1933,1949,1951,1973,1979,1987,1993,1997,1999};
22 
23 int n, m, hash[MAXN], map[MAXN], MOD, size;
24 
25 //选择恰比n大的素数
26 int chooseLuckyOne(int n){for(int i = 0;;i++)if(prime[i] >= n)return prime[i];}
27 
28 int getPos(int x){  //找到x的可用位置
29     int cur = x % MOD;
30     while(hash[cur] != tan90){
31         cur++;
32         if(cur > size)cur = 0;
33     }
34     return cur;
35 }
36 
37 int query(int x){   //查询value为x的元素在散列表中的位置
38     int cur = x % MOD;
39     while(x != hash[cur]){
40         cur++;
41         if(cur>size)cur = 0;
42     }
43     return cur;
44 }
45 
46 void add(int x){    //向散列表中加入x
47     int cur   = getPos(x);
48     hash[cur] = x;
49     map[x]    = cur;
50 }
51 
52 void del(int x){    //删除value为x的元素
53     int cur   = query(x);
54     hash[cur] = tan90;
55     map[x]    = tan90;
56 }
57 
58 //打印散列表,用于调试
59 void print(){for(int i = 0;i <= size; i++)printf("key = %d, value = %d\n", i, hash[i]);}
60 
61 void init(){
62     scanf("%d", &n);
63     MOD = chooseLuckyOne(n);
64     size = MOD - 1;
65     for(int i = 0; i <= size; i++)hash[i] = tan90;
66     for(int i = 1;i <= n;i++){
67         int a;
68         scanf("%d", &a);
69         add(a);
70     }
71     print();
72     scanf("%d", &m);
73     for(int i = 1; i <= m; i++){
74         int ctrl, x;    // 1 x 表示加入x, 2 x表示删除value为x的元素
75         scanf("%d%d", &ctrl, &x);
76         if(ctrl == 1)add(x);
77         if(ctrl == 2)del(x);
78     }
79 }
80 
81 int main(int argc, char const *argv[]){
82     init();
83     print();
84     return 0;
85 }
Hash

 

 链式前向星(完成图的遍历):

 1 #define MAXN 500010
 2 #include <cstdio>
 3 using namespace std;
 4 
 5 int cnt = 0, head[MAXN], n, m;
 6 
 7 struct edge{
 8     int next;   //指向下一条边的下标
 9     int to;     //也就是此边的end
10     int w;      //边权
11 }E[MAXN];
12 
13 void addEdge(int u, int v, int w){
14     E[++cnt].next = head[u];    //要牢记链式前向星是倒序存储这一事实
15     E[cnt].w      = w;
16     E[cnt].to     = v;
17     head[u]       = cnt;
18 }
19 
20 void print(){   //模板功能,遍历全图
21     for(int j=1;j<=m;j++)
22     for(int i=head[j];i;i=E[i].next){
23         printf("Start:%d\nEnd:%d\nWeight:%d\n", j, E[i].to, E[i].w);
24     }
25 }
26 
27 int main(int argc, char const *argv[]){
28     int a, b, c;
29     scanf("%d%d", &n, &m);  //这里n个节点,m条边
30     for(int i=1;i<=m;i++){
31         scanf("%d%d%d", &a, &b, &c);
32         addEdge(a, b, c);
33     }
34     print();
35     return 0;
36 }
链式前向星

 

 快速输入输出:

 1 inline void read(int &x){
 2     char ch=getchar();x=0;int f;while(ch==' '||ch=='\n'||ch=='\r')ch=getchar();
 3     if(ch=='-'){f=-1;ch=getchar();}else f=1;
 4     while(ch!=' '&&ch!='\n'&&ch!='\r'){x=x*10+ch-'0';ch=getchar();}x*=f;
 5 }
 6 
 7 inline void write(int x){
 8     if(x<0){putchar('-');x=-x;}
 9     if(x>9)write(x/10);putchar(x%10+48);
10 }
11 
12 inline void writeln(int x){write(x);putchar('\n');}
外挂

 PS:对上一个版本进行了修改,使其同时支持Windows/Linux 在Windows下特判一下\r\n即可(一晚上的泪啊)

UPdate:快读负优化。。看来不能用了

又Update:现在看来原来的快读并没有问题,不会负优化,而且效果显著(实测在1e6的数据下可以快300ms左右);反而是简化版(不支持负数)的快读出了问题=w=

1 inline void read(int &x){char c=getchar();while(!((c>=48)&&(c<='9')))c=getchar();while((c>=48)&&(c<='9'))x=x*10+c-48,c=getchar();}
快读,不支持负数

 

 筛法求素数:

  埃氏筛法仍然是十分高效的素数筛法,优化一下常数,在1e8的数据下依然不逊色于线性筛(而且码起来又快又准)

1 // 预处理
2 memset(primeQ,true,sizeof(primeQ));primeQ[0]=primeQ[1]=false;
3 
4 // 一个小小的优化,筛的上限只要到读入数据的最大值就可以了
5 rep(1,m){read(a[i]);if(a[i]>__mAx)__mAx=a[i];}
6 
7 rep(2,__mAx)if(primeQ[i])for(register int j=i*2;j<=__mAx;j+=i)primeQ[j]=false;
埃氏筛法
 
堆优化Dijkstra:
 1 #define rep(x,y) for(register int i=(x);i<=(y);i++)
 2 #define MAXN 10003
 3 #define MAXM 500003
 4 #define INF  0x3f3f3f3f
 5 #include <bits/stdc++.h>
 6 using namespace std;
 7 
 8 inline void read(int &x){
 9     char ch=getchar();x=0;int f;while(ch==' '||ch=='\n'||ch=='\r')ch=getchar();
10     if(ch=='-'){f=-1;ch=getchar();}else f=1;
11     while(ch!=' '&&ch!='\n'&&ch!='\r'){x=x*10+ch-'0';ch=getchar();}x*=f;
12 }
13 
14 struct edge{
15     int u, v, w;
16     int next;
17 }G[MAXM];
18 
19 struct node{
20     int w,now;
21     inline bool operator <(const node x)const{return w>x.w;}
22 };
23 
24 int head[MAXN], cnt, n, m, s, dis[MAXN];
25 bool vis[MAXN];
26 priority_queue<node> q;
27 
28 inline void add(int u,int v,int w){
29     G[++cnt].u=u;
30     G[cnt].v=v;
31     G[cnt].w=w;
32     G[cnt].next=head[u];
33     head[u]=cnt;
34 }
35 
36 inline void dijkstra(){
37     memset(dis, 0x3f, sizeof(dis));dis[s]=0;
38     memset(vis, false, sizeof(vis));
39     q.push((node){0,s});
40     while(!q.empty()){
41         node x=q.top();q.pop();
42         int u=x.now;
43         if(!vis[u]){
44             vis[u]=true;
45             for(int i=head[u];i;i=G[i].next){
46                 int v=G[i].v;
47                 dis[v]=min(dis[v], dis[u]+G[i].w);
48                 q.push((node){dis[v], v});
49             }
50         }
51     }
52 }
53 
54 int main(int argc, char const *argv[]){
55     read(n);read(m);read(s);
56     rep(1,m){
57         int a,b,c;
58         read(a);read(b);read(c);
59         add(a,b,c);
60     }
61     dijkstra();
62     rep(1,n){
63         if(dis[i]==INF)printf("2147483647 ");
64         else printf("%d ", dis[i]);
65     }
66     return 0;
67 }
对应洛谷P3371

 

转载于:https://www.cnblogs.com/mojibake/p/9130230.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值