樸素樹狀數組:node
區間加,並不帶lazy tag(lowbit()表)c++
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
簡單並查集:算法
沒有套在最小生成樹等算法中,只是一個簡單的實現ubuntu
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 */
哈希表:數組
只是簡單的數字存儲(其實寫的很蠢並且無甚可移植性)ide
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便可(一夜的淚啊)ui
UPdate:快讀負優化。。看來不能用了spa
又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;
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 }