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


    [ 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
    ", 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
    ", 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
    ", 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
    ", phi[i]);
    58   // while( ~scanf("%lld", &n) ) printf("%lld
    ", 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
    ", 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
    ", 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
    ", 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
    ", Querry_sum(u, v)); break;
    136       case 'M': printf("%d
    ", 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
    ", 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
    ", 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
    ", ans.first, ans.second);
    78 
    79   fclose(stdin), fclose(stdout);
    80   return 0;
    81 }
    2018.07.05

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

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

  • 相关阅读:
    linux基本命令
    Charles抓包
    html5基础知识
    java流程控制
    Harry Potter and the sorcerer's stone-01 the Boy Who Lived
    java基础知识
    Java程序运行机制
    java基础相关(历史,特性,环境变量)
    markdown基本语法
    Dos相关知识
  • 原文地址:https://www.cnblogs.com/nanjoqin/p/9691357.html
Copyright © 2020-2023  润新知