[模板] 一些要复习的模板

[ Letter Song - 初音Miku (Author: dokiyo) ]

机房挂上了高级电子牌子,说是离 NOIp 还有 49 天。

挺红挺亮的,也很扎眼,一抬头就看得见,和自己算的日子差不多,但是想一想,还是比自己感觉到的还更近一些。

搞得自己越来越虚。

越临近考试反而状态越差了的感觉,考试也是随随便便就被别人吊打,做不动题也打不起精神。

很难想象这样的自己要是真的没拿到奖会变成什么样子,几个星期前信誓旦旦要拿一等奖的热血倒是已经凉了一半了。

看着两年多前办的一中饭卡,卡面已经昏黄布满一些细碎的划痕,还有两年多前贴上的卡贴,有种怅然若失的感觉呢。

背离过,也尝试寻找过拾起过,所谓初心的东西。

就顺手整理一些还不太会的模板以便复习吧,有些也比较远古了,可能比较丑,不过应该不影响食用……如果以后写相关的博客,大概也会在这里挂一下的。

 

1. KMP算法

 1 #include <cstdio> 
 2 #include <cctype> 
 3 #include <cstring> 
 4 #include <algorithm> 
 5 using namespace std; 
 6 
 7 const int maxl = 1000000 + 10; 
 8 char a[maxl], b[maxl]; 
 9 int ans[maxl], nxt[maxl], lena, lenb; 
10 
11 int main(int argc, char const *argv[]) 
12 { 
13   scanf("%s%s", a, b); 
14   lena = strlen(a), lenb = strlen(b); 
15   int t = 0;  nxt[0] = 0;
16   for(int i = 1; i < lenb; ++i) {
17     while( t && b[i] != b[t] ) t = nxt[t - 1];
18     if( b[i] == b[t] ) ++t;  nxt[i] = t;
19   }
20   int k = 0;  t = 0;
21   for(int i = 0; i < lena; ++i) {
22     while( t && a[i] != b[t] )  t = nxt[t - 1];
23     if( a[i] == b[t] )  ++t;
24     if( t == lenb )  ans[++k] = i - lenb + 2;
25   }
26   for(int i = 1; i <= k; ++i) printf("%d\n", ans[i]);
27   for(int i = 0; i < lenb; ++i) printf("%d ", nxt[i]);
28   return 0;
29 }
2018.06.27

 

2. Manacher算法

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 
 6 const int maxn = 11000000 + 10;
 7 char tmp[maxn], s[maxn << 1];
 8 int l, p[maxn << 1];
 9 
10 inline int Manacher() {
11   int ans = 0, pos = 0;
12   for(int i = 0; i <= l; ++i) {
13     if( pos + p[pos] > i ) p[i] = min(p[2 * pos - i], pos + p[pos] - i);
14     while( i - p[i] >= 0 && i + p[i] <= l && s[i - p[i]] == s[i + p[i]] ) 
15       ++p[i];
16     if( pos + p[pos] < i + p[i] ) pos = i;
17     ans = max(ans, p[i]);
18   }
19   return ans - 1;
20 }
21 
22 int main(int argc, char const *argv[])
23 {
24   scanf("%s", tmp);
25   int len = strlen(tmp); l = -1;
26   for(int i = 0; i < len; ++i)
27     s[++l] = '#', s[++l] = tmp[i];
28   s[++l] = '#';
29   printf("%d\n", Manacher());
30 
31   return 0;
32 }
2018.06.27

 

3. AC自动机(丑死了)

  1 // Warning: There Is An Error In This Code.
  2 // When There Are Two Strings That One Is Included By The Other.
  3 // It Will Give A Wrong Answer.
  4 // By. Kimitsu Nanjo In 06.28.2018.
  5 // https://www.luogu.org/problemnew/show/P3796
  6 
  7 #include <cstdio>
  8 #include <cstdlib>
  9 #include <cstring>
 10 #include <algorithm>
 11 
 12 const int maxn = 1000000 + 10;
 13 char a[maxn], word[maxn];
 14 
 15 struct Node{
 16   int cnt;
 17   Node *fail, *next[26];
 18 }*queue[maxn], *root;
 19 
 20 inline void Refl(Node *root) {
 21   root->cnt = 0;
 22   root->fail = NULL;
 23   for(int i = 0; i < 26; ++i)
 24     root->next[i] = NULL;
 25 }
 26 
 27 inline void Insert(char *s, int len) {
 28   Node *p = root;
 29   for(int i = 0; i < len; ++i) {
 30     if( p->next[s[i] - 'a'] == NULL ) {
 31       Node *q = (Node*)malloc(sizeof(Node)); Refl(q);
 32       p->next[s[i] - 'a'] = q;
 33     }
 34     p = p->next[s[i] - 'a'];
 35   }
 36   p->cnt++;
 37 }
 38 
 39 inline void Build_fail(Node *root) {
 40   int head = 0, tail = 0;   //队列头、尾指针 
 41   queue[head++] = root;   //先将root入队 
 42   while( head != tail )
 43   {
 44     Node *p = NULL, *temp = queue[tail++];    //弹出队头结点 
 45     for(int i = 0; i < 26; ++i) {
 46       if( temp->next[i] != NULL ) {
 47             //找到实际存在的字符结点
 48             //temp->next[i] 为该结点,temp为其父结点 
 49         if( temp == root ) temp->next[i]->fail = root;
 50             //若是第一层中的字符结点,则把该结点的失败指针指向root 
 51         else {
 52               //依次回溯该节点的父节点的失败指针直到某节点的next[i]与该节点相同
 53               //则把该节点的失败指针指向该next[i]节点; 
 54               //若回溯到 root 都没有找到,则该节点的失败指针指向 root
 55           p = temp->fail;   //将该结点的父结点的失败指针给p 
 56           while( p != NULL ) {
 57             if( p->next[i] != NULL ) {
 58               temp->next[i]->fail = p->next[i];
 59               break;
 60             }
 61             p = p->fail;
 62           }
 63               //让该结点的失败指针也指向root 
 64           if( p == NULL ) temp->next[i]->fail = root;
 65         }
 66         queue[head++] = temp->next[i];
 67             //每处理一个结点,都让该结点的所有孩子依次入队 
 68       }
 69     }
 70   }
 71 }
 72 
 73 inline int Querry(Node *root, int len) {    //i为主串指针,p为模式串指针 
 74   int ans = 0;
 75   Node *p = root;
 76   for(int i = 0; i < len; ++i) {
 77         //由失败指针回溯查找,判断s[i]是否存在于Trie树中 
 78     while( p->next[a[i] - 'a'] == NULL && p != root ) p = p->fail;
 79     p = p->next[a[i] - 'a'];    //找到后p指针指向该结点 
 80     if( p == NULL ) p = root;   //若指针返回为空,则没有找到与之匹配的字符 
 81     Node *temp = p;   //匹配该结点后,沿其失败指针回溯,判断其它结点是否匹配 
 82     while( temp != root ) {   //匹配结束控制 
 83       if( temp->cnt >= 0 )   //判断该结点是否被访问 
 84         ans += temp->cnt, temp->cnt = -1;
 85           //由于cnt初始化为 0,所以只有cnt>0时才统计了单词的个数, 标记已访问过 
 86       temp = temp->fail;    //回溯 失败指针 继续寻找下一个满足条件的结点 
 87     }
 88   }
 89   return ans;
 90 }
 91 
 92 void Free_Node(Node *p) {
 93   for(int i = 0; i < 26; ++i)
 94     if( p->next[i] != NULL ) Free_Node(p->next[i]);
 95   free(p);
 96 }
 97 
 98 int main(int argc, char* const argv[])
 99 {
100   int n = 0;
101   root = (struct Node*)malloc(sizeof(Node)), Refl(root);
102   scanf("%d", &n);
103   for(int i = 1; i <= n; ++i) {
104     scanf("%s", word);
105     Insert(word, strlen(word));
106   }
107   Build_fail(root);
108   scanf("%s", a);
109   printf("%d\n", Querry(root, strlen(a)));
110 
111   return 0;
112 }
2018.06.29

 

4. 求欧拉函数

 1 #include <cctype>
 2 #include <cstdio>
 3 #include <cstdlib>
 4 #include <cstring>
 5 #include <algorithm>
 6 using namespace std;
 7 
 8 typedef long long u64;
 9 const int maxn = 10000000 + 10;
10 int n, prime[maxn], not_pri[maxn], phi[maxn];
11 
12 /* 单个欧拉函数 */
13 inline u64 Sig_Phi(u64 x) {
14   u64 phi = x;
15   for(u64 i = 2; i * i <= x; ++i) {
16     if( !(x % i) ) {
17       phi = phi - phi / i;
18       while( !(x % i) ) x /= i;
19     }
20   }
21   if( x > 1 ) phi = phi - phi / x;
22   return phi;
23 }
24 
25 /* 线性求欧拉函数 */
26 inline void Che_Phi(u64 x) {
27   phi[1] = 1;
28   for(int i = 2; i < x; ++i) phi[i] = i;
29   for(int i = 2; i < x; ++i) {
30     if( phi[i] == i ) for(int j = i; j < x; j += i)
31       phi[j] = phi[j] / i * (i - 1);
32   }
33 }
34 
35 /* 线性求欧拉函数 */
36 inline void Get_Phi(u64 x) {
37   int p = -1, k;
38   phi[1] = 1, not_pri[0] = not_pri[1] = 1;
39   for(int i = 2; i <= x; ++i) {
40     if( !not_pri[i] ) {
41       prime[++p] = not_pri[i] = i;
42       phi[i] = i - 1;
43     }
44     for(int j = 0; j <= p; ++j) {
45       if( (k = prime[j] * i) > x ) break;
46       not_pri[k] = prime[j];
47       if( not_pri[i] == prime[j] ) {
48         phi[k] = phi[i] * prime[j]; break;
49       } else phi[k] = phi[i] * (prime[j] - 1);
50     }
51   }
52 }
53 
54 int main(int argc, char* const argv[])
55 {
56   Get_Phi(10000000);
57   for(int i = 1; i <= 20; ++i) printf("%d\n", phi[i]);
58   // while( ~scanf("%lld", &n) ) printf("%lld\n", Phi(n));
59 
60   return 0;
61 }
2018.09.19

 

5. 中国剩余定理(含拓欧)

 1 #include <cctype>
 2 #include <cstdio>
 3 #include <cstdlib>
 4 #include <cstring>
 5 #include <algorithm>
 6 using namespace std;
 7 
 8 typedef long long int u64;
 9 
10 u64 Ex_gcd(u64 a, u64 b, u64 &x, u64 &y) {
11   if( !b ) { x = 1, y = 0; return a; }
12   u64 d = Ex_gcd(b, a % b, x, y), tmp = x;
13   x = y, y = tmp - a / b * y;
14   return d;
15 }
16 
17 u64 CRT(u64 *a, u64 *b, u64 k) {
18   u64 x = 0, y = 0, m = 0, mul = 1, ans = 0;
19   for(int i = 1; i <= k; ++i) mul *= a[i];
20   for(int i = 1; i <= k; ++i) {
21     m = mul / a[i];
22     Ex_gcd(m, a[i], x, y);
23     ans = (ans + m * x * b[i]) % mul;
24   }
25   return ans > 0 ? ans : ans + mul;
26 }
27 
28 int main(int argc, char* const argv[])
29 {
30   u64 n = 0, a[12] = {0}, b[12] = {0};
31   scanf("%lld", &n);
32   for(int i = 1; i <= n; ++i)
33     scanf("%lld%lld", &a[i], &b[i]);
34   printf("%lld\n", CRT(a, b, n));
35 
36   return 0;
37 }
2018.07.01

 

6. ST表

 1 /*
 2     ST表是利用的是倍增的思想
 3     拿最大值来说
 4     我们用Max[i][j]表示,从i位置开始的2^j个数中的最大值,
 5     例如Max[i][1]表示的是i位置和i+1位置中两个数的最大值.
 6     查询的时候也比较简单,我们计算出log2(区间长度)
 7     然后对于左端点和右端点分别进行查询,这样可以保证一定可以覆盖查询的区间
 8     刚开始学的时候我不太理解为什么从右端点开始查的时候左端点是r−2k+1
 9     实际很简单,因为我们需要找到一个点x,使得x+2k−1=r
10     这样的话就可以得到x=r−2k+1
11 */
12 #include <cstdio>
13 #include <cctype>
14 #include <cstring>
15 #include <algorithm>
16 using namespace std;
17 
18 const int maxn = 1e5 + 10;
19 const int maxm = 1e6 + 10;
20 int n, m, a[maxn][21], lg[maxn];
21 
22 inline void read(int &x) {
23     register char ch = 0;  x = 0;
24     while( !isdigit(ch) ) ch = getchar();
25     while( isdigit(ch) ) x = (x * 10) + (ch ^ 48), ch = getchar();
26 }
27 
28 int main() {
29     scanf("%d%d", &n, &m);
30     for(int i = 1; i <= n; ++i) read(a[i][0]);
31     for(int j = 1; j <= 20; ++j)
32         for(int i = 1; i + (1 << j) - 1 <= n; ++i)    //注意这里要控制边界 
33                 a[i][j] = max(a[i][j - 1], a[i + (1 << (j - 1))][j - 1]);
34     int tmp = 3;
35     for(int i = 3; i <= n; ++i) {        // 处理log2(i)
36         lg[i] = lg[i - 1];
37         if( i == tmp )  ++lg[i], tmp = (tmp << 1) - 1;
38     }
39     int l, r, ans;
40     for(int i = 1; i <= m; ++i) {
41         read(l), read(r);
42         int t = lg [r - l + 1];
43         ans = max(a[l][t], a[r - (1 << t) + 1][t]);    //把拆出来的区间分别取最值 
44         printf("%d\n", ans);
45     }
46     return 0;
47 }
2018.05.03

 

7. 割点

 1 #include<cstdio>
 2 #include<cctype>
 3 #include<algorithm>
 4 using namespace std;
 5 
 6 const int neko = 200000 + 10;
 7 int n, m, head[neko], stack[neko], t, p, top, dfn_num, col_num, edge_num;
 8 int cut[neko], ans[neko], dfn[neko], low[neko], col[neko], cnt[neko];
 9 
10 struct Edge { int u, v, nxt; } edge[neko << 1];
11 
12 inline int read() {
13   register char ch = 0; register int w = 0, x = 0;
14   while( !isdigit(ch) ) w |= (ch == '-'), ch = getchar();
15   while( isdigit(ch) ) x = (x * 10) + (ch ^ 48), ch = getchar();
16   return w ? -x : x;
17 }
18 
19 void Tarjan(int s) {
20   int root = 0;
21   dfn[s] = low[s] = ++dfn_num, stack[++top] = s;
22   for(int i = head[s]; i; i = edge[i].nxt) {
23     if( !dfn[edge[i].v] ) {
24       Tarjan(edge[i].v), low[s] = min(low[s], low[edge[i].v]);
25       if ( low[edge[i].v] >= dfn[s] && s != p ) cut[s] = 1;
26       if ( s == p ) ++root;
27     }
28     low[s] = min(low[s], dfn[edge[i].v]);
29     if( s == p && root >= 2 ) cut[s] = 1;
30   }
31 }
32 
33 int main() {
34   scanf("%d%d", &n, &m);
35   for(int x, y, i = 1; i <= m; ++i) {
36     x = read(), y = read();
37     edge[++edge_num].u = x, edge[edge_num].v = y;
38     edge[edge_num].nxt = head[x], head[x] = edge_num;
39     edge[++edge_num].u = y, edge[edge_num].v = x;
40     edge[edge_num].nxt = head[y], head[y] = edge_num;
41   }
42   for(int i = 1; i <= n; ++i) if( !dfn[i] )  p = i, Tarjan(i);
43   for(int i = 1; i <= n; ++i) if( cut[i] ) ans[++t] = i;
44   printf("%d\n", t);
45   for(int i = 1; i <= t; ++i) printf("%d ", ans[i]);
46   return 0;
47 }
2018.04.10

 

8. 树链剖分

  1 #include <queue>
  2 #include <cctype>
  3 #include <cstdio>
  4 #include <cstring>
  5 #include <algorithm>
  6 using namespace std;
  7 
  8 #define lch (x << 1)
  9 #define rch (x << 1) | 1
 10 
 11 const int iinf = 2147483647;
 12 const int maxn = 60000 + 10;
 13 int n, head[maxn], value[maxn], dfn[maxn], idfn[maxn], dfn_num;
 14 int top[maxn], size[maxn], son[maxn], pre[maxn], deep[maxn], edge_num;
 15 
 16 struct Edge{ int v, nxt; }edge[maxn << 1];
 17 
 18 class Seg_tree{
 19   private:
 20     int mas[maxn << 1] = {0}, sum[maxn << 1] = {0};
 21   public:
 22     inline void Maintain(int x) {
 23       sum[x] = sum[lch] + sum[rch];
 24       mas[x] = max(mas[lch], mas[rch]);
 25     }
 26 
 27     void Build(int x, int l, int r) {
 28       if( l == r ) { sum[x] = mas[x] = value[idfn[l]];  return ; }
 29       int mid = (l + r) >> 1;
 30       Build(lch, l, mid), Build(rch, mid + 1, r);
 31       Maintain(x);
 32     }
 33 
 34     void Update(int x, int l, int r, int ques, int num) {
 35       if( l == r ) { sum[x] = mas[x] = num;  return ; }
 36       int mid = (l + r) >> 1;
 37       if( ques <= mid ) Update(lch, l, mid, ques, num);
 38       else Update(rch, mid + 1, r, ques, num);
 39       Maintain(x);
 40     }
 41 
 42     int Querry_max(int x, int l, int r, int quesl, int quesr) {
 43       if( l >= quesl && r <= quesr ) { return mas[x]; }
 44       int mid = (l + r) >> 1, ans1 = -iinf, ans2 = -iinf;
 45       if( quesl <= mid ) ans1 = Querry_max(lch, l, mid, quesl, quesr);
 46       if( quesr > mid ) ans2 = Querry_max(rch, mid + 1, r, quesl, quesr);
 47       return max(ans1, ans2);
 48     }
 49 
 50     int Querry_sum(int x, int l, int r, int quesl, int quesr) {
 51       if( l >= quesl && r <= quesr ) { return sum[x]; }
 52       int mid = (l + r) >> 1, ans = 0;
 53       if( quesl <= mid ) ans += Querry_sum(lch, l, mid, quesl, quesr);
 54       if( quesr > mid ) ans += Querry_sum(rch, mid + 1, r, quesl, quesr);
 55       return ans;
 56     }
 57 }tree;
 58 
 59 inline int read() {
 60   register char ch = 0; register int w = 0, x = 0;
 61   while( !isdigit(ch) ) w |= (ch == '-'), ch = getchar();
 62   while( isdigit(ch) ) x = (x * 10) + (ch ^ 48), ch = getchar();
 63   return w ? -x : x;
 64 }
 65 
 66 inline void Add_edge(int u, int v) {
 67   edge[++edge_num].v = v;
 68   edge[edge_num].nxt = head[u], head[u] = edge_num;
 69 }
 70 
 71 int Deepfs_1(int x) {
 72   int tmp = 0;
 73   for(int i = head[x]; i; i = edge[i].nxt) {
 74     if( edge[i].v == pre[x] ) continue;
 75     pre[edge[i].v] = x, deep[edge[i].v] = deep[x] + 1;
 76     size[x] += Deepfs_1(edge[i].v);
 77     if( tmp < size[edge[i].v] ) tmp = size[edge[i].v], son[x] = edge[i].v;
 78   }
 79   return head[x] ? ++size[x] : size[x] = 1;
 80 }
 81 
 82 void Deepfs_2(int x, int t) {
 83   top[x] = t, dfn[x] = ++dfn_num, idfn[dfn_num] = x;
 84   if( son[x] ) Deepfs_2(son[x], t);
 85   for(int i = head[x]; i; i = edge[i].nxt)
 86     if( edge[i].v != son[x] && edge[i].v != pre[x] )
 87       Deepfs_2(edge[i].v, edge[i].v);
 88 }
 89 
 90 inline int Querry_max(int x, int y) {
 91   int ans = -iinf;
 92   while( top[x] != top[y] ) {
 93     if( deep[top[x]] >= deep[top[y]] ) {
 94       ans = max(ans, tree.Querry_max(1, 1, n, dfn[top[x]], dfn[x]));
 95       x = pre[top[x]];
 96     } else {
 97       ans = max(ans, tree.Querry_max(1, 1, n, dfn[top[y]], dfn[y]));
 98       y = pre[top[y]];
 99     }
100   }
101   if( dfn[x] > dfn[y] ) swap(x, y);
102   return max(ans, tree.Querry_max(1, 1, n, dfn[x], dfn[y]));
103 }
104 
105 inline int Querry_sum(int x, int y) {
106   int ans = 0;
107   while( top[x] != top[y] ) {
108     if( deep[top[x]] >= deep[top[y]] ) {
109       ans += tree.Querry_sum(1, 1, n, dfn[top[x]], dfn[x]);
110       x = pre[top[x]];
111     } else {
112       ans += tree.Querry_sum(1, 1, n, dfn[top[y]], dfn[y]);
113       y = pre[top[y]];
114     }
115   }
116   if( dfn[x] > dfn[y] ) swap(x, y);
117   return ans + tree.Querry_sum(1, 1, n, dfn[x], dfn[y]);
118 }
119 
120 int main(int argc, char* const argv[])
121 {
122   scanf("%d", &n);
123   for(int i = 1; i < n; ++i) {
124     int u = read(), v = read();
125     Add_edge(u, v), Add_edge(v, u);
126   }
127   for(int i = 1; i <= n; ++i) value[i] = read();
128   size[1] = Deepfs_1(1), Deepfs_2(1, 1), tree.Build(1, 1, n);
129 
130   int q = read();  char ques[10];
131   for(int i = 1; i <= q; ++i) {
132     scanf("%s", ques);
133     int u = read(), v = read();
134     switch( ques[1] ) {
135       case 'S': printf("%d\n", Querry_sum(u, v)); break;
136       case 'M': printf("%d\n", Querry_max(u, v)); break;
137       case 'H': tree.Update(1, 1, n, dfn[u], v); break;
138     }
139   }
140 
141   return 0;
142 }
2018.07.08

 

9. 可持久化线段树

 1 #include <queue>
 2 #include <cstdio>
 3 #include <cctype>
 4 #include <vector>
 5 #include <cstring>
 6 #include <iostream>
 7 #include <algorithm>
 8 using namespace std;
 9 
10 vector<int> id;
11 
12 const int maxn = 2 * 100000 + 10;
13 int n, m, a[maxn], node_num;
14 
15 struct Node {
16   int sum;
17   Node *lchild, *rchild;
18 
19   Node() { sum = 0, lchild = rchild = NULL; }
20   ~Node() {};
21 } node[25 * maxn], *root[maxn];
22 
23 class Segment_tree {
24 public:
25   void Build(Node *root, int l, int r) {
26     root->lchild = &node[++node_num], root->rchild = &node[++node_num];
27     if( l == r ) return ;
28     int mid = (l + r) >> 1;
29     Build(root->lchild, l, mid), Build(root->rchild, mid + 1, r);
30   }
31 
32   void Insert(Node *root, Node *&new_root, int l, int r, int pos) {
33     node[++node_num] = *root, new_root = &node[node_num], ++new_root->sum;
34     if( l == r ) return ;
35     int mid = (l + r) >> 1;
36     if( pos <= mid ) Insert(root->lchild, new_root->lchild, l, mid, pos);
37     else Insert(root->rchild, new_root->rchild, mid + 1, r, pos);
38   }
39 
40   int Querry(Node *root_l, Node *root_r, int l, int r, int pos) {
41     if( l == r ) return l;
42     int mid = (l + r) >> 1, sum = root_r->lchild->sum - root_l->lchild->sum;
43     if( sum >= pos ) return Querry(root_l->lchild, root_r->lchild, l, mid, pos);
44     else return Querry(root_l->rchild, root_r->rchild, mid + 1, r, pos - sum);
45   }
46 } tree;
47 
48 inline int read() {
49   register char ch = 0; register int w = 0, x = 0;
50   while( !isdigit(ch) ) w |= (ch == '-'), ch = getchar();
51   while( isdigit(ch) ) x = (x * 10) + (ch ^ 48), ch = getchar();
52   return w ? -x : x;
53 }
54 
55 inline int Get_num(int x) {
56   return lower_bound(id.begin(), id.end(), x) - id.begin() + 1;
57 }
58 
59 int main(int argc, char const *argv[])
60 {
61   scanf("%d%d", &n, &m);
62   for(int i = 1; i <= n; ++i) a[i] = read(), id.push_back(a[i]);
63   sort(id.begin(), id.end());
64   id.erase(unique(id.begin(), id.end()), id.end());
65   root[0] = &node[0], tree.Build(root[0], 1, n);
66   for(int i = 1; i <= n; ++i) {
67     // printf("%s\n", root[i - 1] == 0 ? "true" : "false");
68     tree.Insert(root[i - 1], root[i], 1, n, Get_num(a[i]));
69   }
70   while( m-- ) {
71     int l = read(), r = read(), k = read();
72     printf("%d\n", id[tree.Querry(root[l - 1], root[r], 1, n, k) - 1]);
73   }
74 
75   return 0;
76 }
2018.09.05

 

10. 费用流

 1 #include <queue>
 2 #include <cctype>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <algorithm>
 6 using namespace std;
 7 
 8 typedef pair<int, int> pairs;
 9 
10 const int maxn = 5000 + 10;
11 const int maxm = 50000 + 10;
12 const int iinf = 0x3f3f3f3f;
13 int n, m, s, t, head[maxn], edge_num;
14 int dis[maxn], vis[maxn], pre[maxn], rec[maxn];
15 
16 struct Edge{ int v, f, c, nxt; }edge[maxm << 1];
17 
18 inline int read() {
19   register char ch = 0; register int x = 0;
20   while( !isdigit(ch) ) ch = getchar();
21   while( isdigit(ch) ) x = (x * 10) +  (ch ^ 48), ch = getchar();
22   return x;
23 }
24 
25 inline void Add_edge(int u, int v, int f, int c) {
26   edge[++edge_num].v = v, edge[edge_num].f = f, edge[edge_num].c = c;
27   edge[edge_num].nxt = head[u], head[u] = edge_num;
28 }
29 
30 inline bool SPFA(int s, int t) {
31   queue<int> q;
32   memset(vis, 0, sizeof vis);
33   memset(dis, 0x3f, sizeof dis);
34   dis[s] = 0, vis[s] = 1, q.push(s);
35   while( !q.empty() ) {
36     int x = q.front();  q.pop();
37     vis[x] = 0;
38     for(int i = head[x]; i; i = edge[i].nxt)
39       if( dis[edge[i].v] > dis[x] + edge[i].c && edge[i].f ) {
40         dis[edge[i].v] = dis[x] + edge[i].c;
41         pre[edge[i].v] = x, rec[edge[i].v] = i;
42         if( !vis[edge[i].v] ) vis[edge[i].v] = 1, q.push(edge[i].v);
43       }
44   }
45   if( dis[t] == iinf ) return false;
46   else return true;
47 }
48 
49 inline pairs Edmond_Karp(int s, int t) {
50   int k, min_flow, min_cost = 0, max_flow = 0;
51   while( SPFA(s, t) ) {
52     k = t, min_flow = iinf;
53     while( k != s ) min_flow = min(min_flow, edge[rec[k]].f), k = pre[k];
54     k = t, max_flow += min_flow;
55     while( k != s ) {
56       min_cost += min_flow * edge[rec[k]].c;
57       if( rec[k] & 1 ) {
58         edge[rec[k]].f -= min_flow, edge[rec[k] + 1].f += min_flow;
59       } else edge[rec[k]].f -= min_flow, edge[rec[k] - 1].f += min_flow;
60       k = pre[k];
61     }
62   }
63   return make_pair(max_flow, min_cost);
64 }
65 
66 int main(int argc, char* const argv[])
67 {
68   freopen("nanjolno.in", "r", stdin);
69   freopen("nanjolno.out", "w", stdout);
70 
71   scanf("%d%d%d%d", &n, &m, &s, &t);
72   for(int i = 1; i <= m; ++i) {
73     int u = read(), v = read(), f = read(), c = read();
74     Add_edge(u, v, f, c), Add_edge(v, u, 0, -c);
75   }
76   pairs ans = Edmond_Karp(s, t);
77   printf("%d %d\n", ans.first, ans.second);
78 
79   fclose(stdin), fclose(stdout);
80   return 0;
81 }
2018.07.05

 

考前持续更新(Before 2018.11.10),大概?

 

                —— 并不需要什么理由,只是因为想做所以去做。 自己真正想做的事情,不就是这样开始的吗。

posted @ 2018-09-22 21:48  南條雪绘  阅读(204)  评论(1编辑  收藏  举报