朴素树状数组:
区间加,并不带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 }
链式前向星(完成图的遍历):
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 }