模板

樸素樹狀數組: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 }
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便可(一夜的淚啊)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;
埃氏篩法
 
堆優化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
相關文章
相關標籤/搜索