• 【 2013 Multi-University Training Contest 2 】


    HDU 4611 Balls Rearrangement

    令lcm=LCM(a,b),gcd=GCD(a,b)。cal(n,a,b)表示sum(abs(i%a-i%b)),0<=i<n。

    显然,答案就是cal(lcm,a,b)*(n/lcm)+cal(n%lcm,a,b)。

    cal(n,a,b)可以通过暴力得到,即对i%a和i%b的值分段,连续的一段(遇到0终止)可以直接得到值。

    因此,每段的长度将直接影响到时间复杂度。

    当lcm较小时,cal中的n不会很大,即使每段长度很小也无所谓。

    当lcm较大时,每段的长度会比较大。

     1 #include<iostream>
     2 #include<algorithm>
     3 typedef long long LL;
     4 using namespace std;
     5 LL GCD(LL x, LL y) {
     6     return y ? GCD(y, x % y) : x;
     7 }
     8 LL LCM(LL x, LL y) {
     9     return x / GCD(x, y) * y;
    10 }
    11 LL cal(LL n, LL a, LL b) {
    12     LL ans = 0;
    13     LL x, y, tmp;
    14     x = 0;
    15     y = a;
    16     for (LL i = a; i < n;) {
    17         tmp = min(a - x, b - y);
    18         if (i + tmp > n) {
    19             tmp = n - i;
    20         }
    21         i += tmp;
    22         ans += tmp * abs(x - y);
    23         x = (x + tmp) % a;
    24         y = (y + tmp) % b;
    25     }
    26     return ans;
    27 }
    28 int main() {
    29     int T;
    30     LL n, a, b;
    31     LL lcm;
    32     LL ans;
    33     cin >> T;
    34     while (T--) {
    35         cin >> n >> a >> b;
    36         if (a == b) {
    37             ans = 0;
    38         } else {
    39             if (a > b) {
    40                 swap(a, b);
    41             }
    42             lcm = LCM(a, b);
    43             ans = (n / lcm) * cal(lcm, a, b) + cal(n % lcm, a, b);
    44         }
    45         cout << ans << endl;
    46     }
    47     return 0;
    48 }
    View Code

    HDU 4612 Warm up

    把桥处理出来,对双连通分量缩点,得到一棵树。

    求树上最长链,将最长链的两端连起来,剩下的桥的个数就是答案。

      1 #pragma comment(linker,"/STACK:102400000,102400000")
      2 
      3 #include<cstdio>
      4 #include<cstring>
      5 #include<algorithm>
      6 #define MAXN 200010
      7 #define MAXM 2000010
      8 using namespace std;
      9 int first[MAXN], next[MAXM], v[MAXM], e;
     10 int dfn[MAXN], low[MAXN];
     11 int belong[MAXN];
     12 bool vis[MAXN];
     13 int n, m;
     14 int dp[MAXN][2];
     15 int father[MAXN];
     16 struct Edge {
     17     int x, y;
     18 };
     19 Edge g[MAXM];
     20 Edge tree[MAXM];
     21 inline void addEdge(int x, int y) {
     22     v[e] = y;
     23     next[e] = first[x];
     24     first[x] = e++;
     25 }
     26 void makeSet(int n) {
     27     for (int i = 0; i <= n; i++) {
     28         father[i] = i;
     29     }
     30 }
     31 int findSet(int x) {
     32     if (father[x] != x) {
     33         father[x] = findSet(father[x]);
     34     }
     35     return father[x];
     36 }
     37 void myUnion(int x, int y) {
     38     x = findSet(x);
     39     y = findSet(y);
     40     if (x != y) {
     41         father[x] = y;
     42     }
     43 }
     44 void dfs(int x, int index, int depth) {
     45     dfn[x] = low[x] = depth;
     46     for (int i = first[x]; i != -1; i = next[i]) {
     47         if ((i ^ 1) == index) {
     48             continue;
     49         }
     50         int y = v[i];
     51         if (dfn[y]) {
     52             low[x] = min(low[x], dfn[y]);
     53         } else {
     54             dfs(y, i, depth + 1);
     55             low[x] = min(low[x], low[y]);
     56             if (low[y] > dfn[x]) {
     57                 tree[m].x = x;
     58                 tree[m++].y = y;
     59             } else {
     60                 myUnion(x, y);
     61             }
     62         }
     63     }
     64 }
     65 void search(int x) {
     66     vis[x] = true;
     67     for (int i = first[x]; i != -1; i = next[i]) {
     68         int y = v[i];
     69         if (!vis[y]) {
     70             search(y);
     71             if (dp[y][0] + 1 >= dp[x][0]) {
     72                 dp[x][1] = dp[x][0];
     73                 dp[x][0] = dp[y][0] + 1;
     74             } else if (dp[y][0] + 1 > dp[x][1]) {
     75                 dp[x][1] = dp[y][0] + 1;
     76             }
     77         }
     78     }
     79 }
     80 int main() {
     81     int i;
     82     int ans;
     83     int cnt;
     84     while (scanf("%d%d", &n, &m), n) {
     85         e = 0;
     86         memset(first, -1, sizeof(first));
     87         for (i = 0; i < m; i++) {
     88             scanf("%d%d", &g[i].x, &g[i].y);
     89             addEdge(g[i].x, g[i].y);
     90             addEdge(g[i].y, g[i].x);
     91         }
     92         makeSet(n);
     93         m = 0;
     94         memset(dfn, 0, sizeof(dfn));
     95         dfs(1, -1, 1);
     96         memset(belong, -1, sizeof(belong));
     97         cnt = 0;
     98         for (i = 1; i <= n; i++) {
     99             if (belong[findSet(i)] == -1) {
    100                 belong[findSet(i)] = ++cnt;
    101             }
    102             belong[i] = belong[findSet(i)];
    103         }
    104         e = 0;
    105         memset(first, -1, sizeof(first));
    106         for (i = 0; i < m; i++) {
    107             addEdge(belong[tree[i].x], belong[tree[i].y]);
    108             addEdge(belong[tree[i].y], belong[tree[i].x]);
    109         }
    110         if (m == 0) {
    111             ans = 0;
    112         } else {
    113             memset(dp, 0, sizeof(dp));
    114             memset(vis, false, sizeof(vis));
    115             search(belong[tree[0].x]);
    116             ans = 0;
    117             for (i = 1; i <= cnt; i++) {
    118                 ans = max(ans, dp[i][0] + dp[i][1]);
    119             }
    120             ans = m - ans;
    121         }
    122         printf("%d
    ", ans);
    123     }
    124     return 0;
    125 }
    View Code

    HDU 4614 Vases and Flowers

    K=1,二分得到起点和终点,区间覆盖为1。

    K=2,区间求和,区间覆盖为0。

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 using namespace std;
      5 #define MAXN 50010
      6 struct node {
      7     int lazy;
      8     int sum;
      9 } tree[MAXN << 2];
     10 inline void pushUp(int rt) {
     11     tree[rt].sum = tree[rt << 1].sum + tree[rt << 1 | 1].sum;
     12 }
     13 void build(int L, int R, int rt) {
     14     tree[rt].lazy = -1;
     15     tree[rt].sum = 0;
     16     if (L != R) {
     17         int mid = (L + R) >> 1;
     18         build(L, mid, rt << 1);
     19         build(mid + 1, R, rt << 1 | 1);
     20     }
     21 }
     22 inline void pushDown(int mid, int L, int R, int rt) {
     23     if (tree[rt].lazy != -1) {
     24         tree[rt << 1].lazy = tree[rt << 1 | 1].lazy = tree[rt].lazy;
     25         tree[rt << 1].sum = tree[rt].lazy * (mid - L + 1);
     26         tree[rt << 1 | 1].sum = tree[rt].lazy * (R - mid);
     27         tree[rt].lazy = -1;
     28     }
     29 }
     30 int sum(int x, int y, int L, int R, int rt) {
     31     if (x <= L && R <= y) {
     32         return tree[rt].sum;
     33     } else {
     34         int mid = (L + R) >> 1;
     35         pushDown(mid, L, R, rt);
     36         int ans = 0;
     37         if (x <= mid) {
     38             ans += sum(x, y, L, mid, rt << 1);
     39         }
     40         if (y > mid) {
     41             ans += sum(x, y, mid + 1, R, rt << 1 | 1);
     42         }
     43         pushUp(rt);
     44         return ans;
     45     }
     46 }
     47 void cover(int x, int y, int val, int L, int R, int rt) {
     48     if (x <= L && R <= y) {
     49         tree[rt].lazy = val;
     50         tree[rt].sum = (R - L + 1) * val;
     51     } else {
     52         int mid = (L + R) >> 1;
     53         pushDown(mid, L, R, rt);
     54         if (x <= mid) {
     55             cover(x, y, val, L, mid, rt << 1);
     56         }
     57         if (y > mid) {
     58             cover(x, y, val, mid + 1, R, rt << 1 | 1);
     59         }
     60         pushUp(rt);
     61     }
     62 }
     63 int main() {
     64     int T;
     65     int n, m;
     66     int k, a, b;
     67     int x, y;
     68     int low, high, mid;
     69     int tot;
     70     scanf("%d", &T);
     71     while (T--) {
     72         scanf("%d%d", &n, &m);
     73         build(0, n - 1, 1);
     74         while (m--) {
     75             scanf("%d%d%d", &k, &a, &b);
     76             if (k == 1) {
     77                 tot = n - a - sum(a, n - 1, 0, n - 1, 1);
     78                 tot = min(tot, b);
     79                 if (tot == 0) {
     80                     puts("Can not put any one.");
     81                 } else {
     82                     low = a;
     83                     high = n;
     84                     while (low < high) {
     85                         mid = (low + high) >> 1;
     86                         if (mid - a + 1 - sum(a, mid, 0, n - 1, 1) >= 1) {
     87                             high = mid;
     88                             x = mid;
     89                         } else {
     90                             low = mid + 1;
     91                         }
     92                     }
     93                     low = a;
     94                     high = n;
     95                     while (low < high) {
     96                         mid = (low + high) >> 1;
     97                         if (mid - a + 1 - sum(a, mid, 0, n - 1, 1) >= tot) {
     98                             high = mid;
     99                             y = mid;
    100                         } else {
    101                             low = mid + 1;
    102                         }
    103                     }
    104                     printf("%d %d
    ", x, y);
    105                     cover(x, y, 1, 0, n - 1, 1);
    106                 }
    107             } else {
    108                 printf("%d
    ", sum(a, b, 0, n - 1, 1));
    109                 cover(a, b, 0, 0, n - 1, 1);
    110             }
    111         }
    112         putchar('
    ');
    113     }
    114     return 0;
    115 }
    View Code

    HDU 4616 Game

    up[i][j][0]表示从下往上走,经历j个障碍的最大收益。

    up[i][j][1]表示从下往上走,经历j个障碍的次大收益。

    down[i][j][0]表示从上往下走,经历j个障碍的最大收益。

    down[i][j][1]表示从上往下走,经历j个障碍的次大收益。

    答案可能由up[i][j][0]+up[i][j][1]-val[i],up[i][j][0]+down[i][j][0]-val[i],up[i][j][1]+down[i][j][0]-val[i],up[i][j][0]+down[i][j][1]-val[i]得到。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #define MAXN 100010
     5 #define MAXM 4
     6 #define oo 987654321
     7 using namespace std;
     8 bool vis[MAXN];
     9 int first[MAXN], next[MAXN], v[MAXN], e;
    10 int n, m;
    11 int val[MAXN], trap[MAXN];
    12 int up[MAXN][MAXM][2], fromUp[MAXN][MAXM][2];
    13 int down[MAXN][MAXM][2], fromDown[MAXN][MAXM][2];
    14 inline void addEdge(int x, int y) {
    15     v[e] = y;
    16     next[e] = first[x];
    17     first[x] = e++;
    18 }
    19 void dfs(int x) {
    20     vis[x] = true;
    21     for (int i = 0; i <= m; i++) {
    22         for (int j = 0; j < 2; j++) {
    23             up[x][i][j] = down[x][i][j] = -oo;
    24         }
    25     }
    26     up[x][trap[x]][0] = val[x];
    27     if (trap[x]) {
    28         down[x][trap[x]][0] = val[x];
    29     }
    30     for (int i = first[x]; i != -1; i = next[i]) {
    31         int y = v[i];
    32         if (!vis[y]) {
    33             dfs(y);
    34             for (int j = trap[x]; j <= m; j++) {
    35                 if (up[x][j][0] <= up[y][j - trap[x]][0] + val[x]) {
    36                     up[x][j][1] = up[x][j][0];
    37                     fromUp[x][j][1] = fromUp[x][j][0];
    38                     up[x][j][0] = up[y][j - trap[x]][0] + val[x];
    39                     fromUp[x][j][0] = y;
    40                 } else if (up[x][j][1] < up[y][j - trap[x]][0] + val[x]) {
    41                     up[x][j][1] = up[y][j - trap[x]][0] + val[x];
    42                     fromUp[x][j][1] = y;
    43                 }
    44                 if (down[x][j][0] <= down[y][j - trap[x]][0] + val[x]) {
    45                     down[x][j][1] = down[x][j][0];
    46                     fromDown[x][j][1] = fromDown[x][j][0];
    47                     down[x][j][0] = down[y][j - trap[x]][0] + val[x];
    48                     fromDown[x][j][0] = y;
    49                 } else if (down[x][j][1] < down[y][j - trap[x]][0] + val[x]) {
    50                     down[x][j][1] = down[y][j - trap[x]][0] + val[x];
    51                     fromDown[x][j][1] = y;
    52                 }
    53             }
    54         }
    55     }
    56 }
    57 int main() {
    58     int T;
    59     int i, j, k;
    60     int x, y;
    61     int ans;
    62     scanf("%d", &T);
    63     while (T--) {
    64         scanf("%d%d", &n, &m);
    65         for (i = 0; i < n; i++) {
    66             scanf("%d%d", &val[i], &trap[i]);
    67         }
    68         e = 0;
    69         memset(first, -1, sizeof(first));
    70         for (i = 1; i < n; i++) {
    71             scanf("%d%d", &x, &y);
    72             addEdge(x, y);
    73             addEdge(y, x);
    74         }
    75         memset(vis, false, sizeof(vis));
    76         dfs(0);
    77         ans = -oo;
    78         for (i = 0; i < n; i++) {
    79             for (j = 0; j <= m; j++) {
    80                 if (j < m) {
    81                     ans = max(ans, up[i][j][0]);
    82                 }
    83                 for (k = 0; k + j <= m; k++) {
    84                     if (fromUp[i][j][0] != fromDown[i][k][0]) {
    85                         ans = max(ans, up[i][j][0] + down[i][k][0] - val[i]);
    86                     } else {
    87                         ans = max(ans, up[i][j][0] + down[i][k][1] - val[i]);
    88                         ans = max(ans, up[i][j][1] + down[i][k][0] - val[i]);
    89                     }
    90                     if (k + j < m) {
    91                         ans = max(ans, up[i][j][0] + up[i][k][1] - val[i]);
    92                     }
    93                 }
    94             }
    95         }
    96         printf("%d
    ", ans);
    97     }
    98     return 0;
    99 }
    View Code

    HDU 4617 Weapon

    对给定的平面求法向量,结合圆心,得到直线。

    求空间直线的距离,若直线i与直线j的最短距离<=半径i+半径j,则相交;否则,答案就是任意两条直线距离的最小值。

      1 #include<cstdio>
      2 #include<cmath>
      3 #include<algorithm>
      4 #define eps 1e-8
      5 #define oo 1e50
      6 #define MAXN 55
      7 using namespace std;
      8 struct point3 {
      9     double x, y, z;
     10 };
     11 struct line3 {
     12     point3 a, b;
     13 };
     14 struct plane3 {
     15     point3 a, b, c;
     16 };
     17 double r[MAXN];
     18 double dis[MAXN][MAXN];
     19 plane3 p[MAXN];
     20 line3 l[MAXN];
     21 double dist(point3 p1, point3 p2) {
     22     return sqrt(
     23             (p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y)
     24                     + (p1.z - p2.z) * (p1.z - p2.z));
     25 }
     26 point3 xmult(point3 u, point3 v) {
     27     point3 ret;
     28     ret.x = u.y * v.z - v.y * u.z;
     29     ret.y = u.z * v.x - u.x * v.z;
     30     ret.z = u.x * v.y - u.y * v.x;
     31     return ret;
     32 }
     33 point3 subt(point3 u, point3 v) {
     34     point3 ret;
     35     ret.x = u.x - v.x;
     36     ret.y = u.y - v.y;
     37     ret.z = u.z - v.z;
     38     return ret;
     39 }
     40 point3 add(point3 u, point3 v) {
     41     point3 ret;
     42     ret.x = u.x + v.x;
     43     ret.y = u.y + v.y;
     44     ret.z = u.z + v.z;
     45     return ret;
     46 }
     47 point3 pvec(plane3 s) {
     48     return xmult(subt(s.a, s.b), subt(s.b, s.c));
     49 }
     50 double dmult(point3 u, point3 v) {
     51     return u.x * v.x + u.y * v.y + u.z * v.z;
     52 }
     53 double vlen(point3 p) {
     54     return sqrt(p.x * p.x + p.y * p.y + p.z * p.z);
     55 }
     56 double linetoline(line3 u, line3 v) {
     57     point3 n = xmult(subt(u.a, u.b), subt(v.a, v.b));
     58     return fabs(dmult(subt(u.a, v.a), n)) / vlen(n);
     59 }
     60 int dbcmp(double x, double y) {
     61     if (fabs(x - y) < eps) {
     62         return 0;
     63     } else {
     64         return x > y ? 1 : -1;
     65     }
     66 }
     67 int main() {
     68     int T;
     69     int n;
     70     int i, j;
     71     point3 tmp;
     72     bool flag;
     73     double ans;
     74     scanf("%d", &T);
     75     while (T--) {
     76         scanf("%d", &n);
     77         for (i = 0; i < n; i++) {
     78             scanf("%lf%lf%lf", &p[i].a.x, &p[i].a.y, &p[i].a.z);
     79             scanf("%lf%lf%lf", &p[i].b.x, &p[i].b.y, &p[i].b.z);
     80             scanf("%lf%lf%lf", &p[i].c.x, &p[i].c.y, &p[i].c.z);
     81             r[i] = dist(p[i].a, p[i].b);
     82             tmp = pvec(p[i]);
     83             l[i].a = p[i].a;
     84             l[i].b = add(l[i].a, tmp);
     85         }
     86         flag = false;
     87         for (i = 0; i < n; i++) {
     88             dis[i][i] = 0;
     89             for (j = i + 1; j < n; j++) {
     90                 dis[i][j] = dis[j][i] = linetoline(l[i], l[j]);
     91             }
     92         }
     93         ans = oo;
     94         for (i = 0; i < n; i++) {
     95             for (j = i + 1; j < n; j++) {
     96                 if (dbcmp(dis[i][j], r[i] + r[j]) <= 0) {
     97                     flag = true;
     98                 } else {
     99                     ans = min(ans, dis[i][j] - r[i] - r[j]);
    100                 }
    101             }
    102         }
    103         if (flag) {
    104             puts("Lucky");
    105         } else {
    106             printf("%.2lf
    ", ans);
    107         }
    108     }
    109     return 0;
    110 }
    View Code

    4618 Palindrome Sub-Array

    回文串要分奇偶考虑。

    分别枚举横,竖的数组,并枚举回文串的中间位置,二分哈希值求出最长回文串。

    枚举横,竖数组的中间位置,二分答案。

    复杂度O(n3log2n),常数比较小。

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #define MAXN 310
      5 #define SEED 100000007
      6 typedef unsigned long long LL;
      7 using namespace std;
      8 int n, m;
      9 int ans;
     10 int arr[MAXN][MAXN];
     11 LL seed[MAXN];
     12 LL hl[MAXN], hr[MAXN];
     13 int r[MAXN][MAXN];
     14 int c[MAXN][MAXN];
     15 void init() {
     16     seed[0] = 1;
     17     for (int i = 1; i < MAXN; i++) {
     18         seed[i] = seed[i - 1] * SEED;
     19     }
     20 }
     21 void hash(int tmp[], int size) {
     22     int i;
     23     hl[0] = tmp[0];
     24     for (i = 1; i < size; i++) {
     25         hl[i] = seed[i] * tmp[i] + hl[i - 1];
     26     }
     27     hr[size - 1] = tmp[size - 1];
     28     for (i = size - 2; i >= 0; i--) {
     29         hr[i] = seed[size - i - 1] * tmp[i] + hr[i + 1];
     30     }
     31 }
     32 bool isOK(int x0, int y0, int x1, int y1, int size) {
     33     if (x0 <= y0 && x1 <= y1) {
     34         LL a = hl[y0];
     35         if (x0 - 1 >= 0) {
     36             a -= hl[x0 - 1];
     37         }
     38         LL b = hr[x1];
     39         if (y1 + 1 < size) {
     40             b -= hr[y1 + 1];
     41         }
     42         if (x0 > size - 1 - y1) {
     43             b *= seed[x0 - (size - 1 - y1)];
     44         } else {
     45             a *= seed[size - 1 - y1 - x0];
     46         }
     47         return a == b;
     48     } else {
     49         return false;
     50     }
     51 }
     52 bool isOddGood(int x, int y, int len) {
     53     int i;
     54     for (i = x - 1; i >= x - len; i--) {
     55         if (r[i][y] < len) {
     56             return false;
     57         }
     58     }
     59     for (i = x + 1; i <= x + len; i++) {
     60         if (r[i][y] < len) {
     61             return false;
     62         }
     63     }
     64     for (i = y - 1; i >= y - len; i--) {
     65         if (c[x][i] < len) {
     66             return false;
     67         }
     68     }
     69     for (i = y + 1; i <= y + len; i++) {
     70         if (c[x][i] < len) {
     71             return false;
     72         }
     73     }
     74     return true;
     75 }
     76 void odd() {
     77     int i, j;
     78     int tmp[MAXN];
     79     int low, high, mid, res;
     80     memset(r, 0, sizeof(r));
     81     for (i = 0; i < n; i++) {
     82         for (j = 0; j < m; j++) {
     83             tmp[j] = arr[i][j];
     84         }
     85         hash(tmp, m);
     86         for (j = 1; j < m - 1; j++) {
     87             res = 0;
     88             low = 0;
     89             high = min(j, m - 1 - j) + 1;
     90             while (low < high) {
     91                 mid = (low + high) >> 1;
     92                 if (isOK(j - mid, j - 1, j + 1, j + mid, m)) {
     93                     res = mid;
     94                     low = mid + 1;
     95                 } else {
     96                     high = mid;
     97                 }
     98             }
     99             r[i][j] = res;
    100         }
    101     }
    102     memset(c, 0, sizeof(c));
    103     for (i = 0; i < m; i++) {
    104         for (j = 0; j < n; j++) {
    105             tmp[j] = arr[j][i];
    106         }
    107         hash(tmp, n);
    108         for (j = 1; j < n - 1; j++) {
    109             res = 0;
    110             low = 0;
    111             high = min(j, n - 1 - j) + 1;
    112             while (low < high) {
    113                 mid = (low + high) >> 1;
    114                 if (isOK(j - mid, j - 1, j + 1, j + mid, n)) {
    115                     res = mid;
    116                     low = mid + 1;
    117                 } else {
    118                     high = mid;
    119                 }
    120             }
    121             c[j][i] = res;
    122         }
    123     }
    124     for (i = 0; i < n; i++) {
    125         for (j = 0; j < m; j++) {
    126             if (r[i][j] && c[i][j]) {
    127                 res = 0;
    128                 low = 0;
    129                 high = min(r[i][j], c[i][j]) + 1;
    130                 while (low < high) {
    131                     mid = (low + high) >> 1;
    132                     if (isOddGood(i, j, mid)) {
    133                         low = mid + 1;
    134                         res = mid;
    135                     } else {
    136                         high = mid;
    137                     }
    138                 }
    139                 ans = max(ans, res << 1 | 1);
    140             }
    141         }
    142     }
    143 }
    144 bool isEvenGood(int x, int y, int len) {
    145     int i;
    146     for (i = x - 1; i > x - len; i--) {
    147         if (r[i][y] < len) {
    148             return false;
    149         }
    150     }
    151     for (i = x + 1; i <= x + len; i++) {
    152         if (r[i][y] < len) {
    153             return false;
    154         }
    155     }
    156     for (i = y - 1; i > y - len; i--) {
    157         if (c[x][i] < len) {
    158             return false;
    159         }
    160     }
    161     for (i = y + 1; i <= y + len; i++) {
    162         if (c[x][i] < len) {
    163             return false;
    164         }
    165     }
    166     return true;
    167 }
    168 void even() {
    169     int i, j;
    170     int tmp[MAXN];
    171     int low, high, mid, res;
    172     memset(r, 0, sizeof(r));
    173     for (i = 0; i < n; i++) {
    174         for (j = 0; j < m; j++) {
    175             tmp[j] = arr[i][j];
    176         }
    177         hash(tmp, m);
    178         for (j = 1; j < m - 1; j++) {
    179             res = 0;
    180             low = 0;
    181             high = min(j + 1, m - 1 - j) + 1;
    182             while (low < high) {
    183                 mid = (low + high) >> 1;
    184                 if (isOK(j - mid + 1, j, j + 1, j + mid, m)) {
    185                     res = mid;
    186                     low = mid + 1;
    187                 } else {
    188                     high = mid;
    189                 }
    190             }
    191             r[i][j] = res;
    192         }
    193     }
    194     memset(c, 0, sizeof(c));
    195     for (i = 0; i < m; i++) {
    196         for (j = 0; j < n; j++) {
    197             tmp[j] = arr[j][i];
    198         }
    199         hash(tmp, n);
    200         for (j = 1; j < n - 1; j++) {
    201             res = 0;
    202             low = 0;
    203             high = min(j + 1, n - 1 - j) + 1;
    204             while (low < high) {
    205                 mid = (low + high) >> 1;
    206                 if (isOK(j - mid + 1, j, j + 1, j + mid, n)) {
    207                     res = mid;
    208                     low = mid + 1;
    209                 } else {
    210                     high = mid;
    211                 }
    212             }
    213             c[j][i] = res;
    214         }
    215     }
    216     for (i = 0; i < n; i++) {
    217         for (j = 0; j < m; j++) {
    218             if (r[i][j] && c[i][j]) {
    219                 res = 0;
    220                 low = 0;
    221                 high = min(r[i][j], c[i][j]) + 1;
    222                 while (low < high) {
    223                     mid = (low + high) >> 1;
    224                     if (isEvenGood(i, j, mid)) {
    225                         low = mid + 1;
    226                         res = mid;
    227                     } else {
    228                         high = mid;
    229                     }
    230                 }
    231                 ans = max(ans, res << 1);
    232             }
    233         }
    234     }
    235 }
    236 int main() {
    237     int T;
    238     int i, j;
    239     init();
    240     scanf("%d", &T);
    241     while (T--) {
    242         scanf("%d%d", &n, &m);
    243         for (i = 0; i < n; i++) {
    244             for (j = 0; j < m; j++) {
    245                 scanf("%d", &arr[i][j]);
    246             }
    247         }
    248         ans = 1;
    249         odd();
    250         even();
    251         printf("%d
    ", ans);
    252     }
    253     return 0;
    254 }
    View Code

    HDU 4619 Warm up 2

    有冲突的两个骨牌连边,求最大匹配。

    最大独立集=顶点数-最大匹配。

      1 #pragma comment(linker,"/STACK:102400000,102400000")
      2 
      3 #include<cstdio>
      4 #include<cstring>
      5 #include<vector>
      6 #define MAXN 100010
      7 #define MAXM 1000010
      8 #define oo 123456789
      9 using namespace std;
     10 int first[MAXN], next[MAXM], v[MAXM], cost[MAXM], e;
     11 int n, m;
     12 int src, des;
     13 inline void addEdge(int x, int y, int val) {
     14     v[e] = y;
     15     cost[e] = val;
     16     next[e] = first[x];
     17     first[x] = e++;
     18 
     19     v[e] = x;
     20     cost[e] = 0;
     21     next[e] = first[y];
     22     first[y] = e++;
     23 }
     24 int SAP() {
     25     int pre[MAXN], cur[MAXN], dis[MAXN], gap[MAXN];
     26     int flow = 0;
     27     int aug = oo;
     28     int x, y;
     29     bool flag;
     30     for (int i = 0; i < n; i++) {
     31         cur[i] = first[i];
     32         gap[i] = dis[i] = 0;
     33     }
     34     gap[src] = n;
     35     x = pre[src] = src;
     36     while (dis[src] < n) {
     37         flag = false;
     38         for (int &j = cur[x]; j != -1; j = next[j]) {
     39             y = v[j];
     40             if (cost[j] > 0 && dis[x] == dis[y] + 1) {
     41                 flag = true;
     42                 aug = min(aug, cost[j]);
     43                 pre[y] = x;
     44                 x = y;
     45                 if (x == des) {
     46                     flow += aug;
     47                     while (x != src) {
     48                         x = pre[x];
     49                         cost[cur[x]] -= aug;
     50                         cost[cur[x] ^ 1] += aug;
     51                     }
     52                     aug = oo;
     53                 }
     54                 break;
     55             }
     56         }
     57         if (flag) {
     58             continue;
     59         }
     60         int tmp = n;
     61         for (int j = first[x]; j != -1; j = next[j]) {
     62             y = v[j];
     63             if (cost[j] > 0 && dis[y] < tmp) {
     64                 tmp = dis[y];
     65                 cur[x] = j;
     66             }
     67         }
     68         if ((--gap[dis[x]]) == 0) {
     69             break;
     70         }
     71         gap[dis[x] = tmp + 1]++;
     72         x = pre[x];
     73     }
     74     return flow;
     75 }
     76 struct Point {
     77     int x, y;
     78 };
     79 struct Line {
     80     Point a, b;
     81 };
     82 Line p[MAXN], q[MAXN];
     83 bool equal(Point s, Point t) {
     84     return s.x == t.x && s.y == t.y;
     85 }
     86 int main() {
     87     int i, j;
     88     int ans;
     89     while (scanf("%d%d", &n, &m), n) {
     90         e = 0;
     91         memset(first, -1, sizeof(first));
     92         src = n + m;
     93         des = src + 1;
     94         for (i = 0; i < n; i++) {
     95             scanf("%d%d", &p[i].a.x, &p[i].a.y);
     96             p[i].b = p[i].a;
     97             p[i].b.x++;
     98             addEdge(src, i, 1);
     99         }
    100         for (i = 0; i < m; i++) {
    101             scanf("%d%d", &q[i].a.x, &q[i].a.y);
    102             q[i].b = q[i].a;
    103             q[i].b.y++;
    104             addEdge(n + i, des, 1);
    105         }
    106         for (i = 0; i < n; i++) {
    107             for (j = 0; j < m; j++) {
    108                 if (equal(p[i].a, q[j].a) || equal(p[i].a, q[j].b)
    109                         || equal(p[i].b, q[j].a) || equal(p[i].b, q[j].b)) {
    110                     addEdge(i, n + j, 1);
    111                 }
    112             }
    113         }
    114         ans = n + m;
    115         n = des + 1;
    116         ans -= SAP();
    117         printf("%d
    ", ans);
    118     }
    119     return 0;
    120 }
    View Code

     

    4620 Fruit Ninja Extreme

    题目要求对于有奖励的切法,时间间隔不超过w,求有奖励切法的最大次数。

    如果一个切法得不到奖励,那么应该选择不切。

    考虑用搜索解决,没有剪枝的情况下,时间复杂度为230

    假设当前在cur,把cur之后的所有切法都假设是最优的,却无法更新答案,那么就没有必要再搜下去了。

    这样可以把时间复杂度降低到可以接受的范围内。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #define MAXN 210
     5 using namespace std;
     6 int n, m, w;
     7 bool vis[MAXN];
     8 struct node {
     9     int time;
    10     int fruit[MAXN];
    11     int cnt;
    12     int pos;
    13     friend bool operator<(node a, node b) {
    14         return a.time < b.time;
    15     }
    16 } arr[MAXN];
    17 int tmp[MAXN], tmpSize;
    18 int ans[MAXN], ansSize;
    19 void dfs(int cur, int pre, int left) {
    20     if (tmpSize > ansSize) {
    21         ansSize = tmpSize;
    22         for (int i = 0; i < tmpSize; i++) {
    23             ans[i] = tmp[i];
    24         }
    25     }
    26     if (left < 3) {
    27         return;
    28     }
    29     if (cur >= n) {
    30         return;
    31     }
    32     if (n - cur + tmpSize <= ansSize) {
    33         return;
    34     }
    35     int cut[MAXN], cutSize;
    36     for (int i = cur; i < n; i++) {
    37         if (pre != -1 && arr[i].time - arr[pre].time > w) {
    38             break;
    39         }
    40         cutSize = 0;
    41         for (int j = 0; j < arr[i].cnt; j++) {
    42             if (!vis[arr[i].fruit[j]]) {
    43                 cut[cutSize++] = arr[i].fruit[j];
    44             }
    45         }
    46         if (cutSize < 3) {
    47             continue;
    48         }
    49         for (int j = 0; j < cutSize; j++) {
    50             vis[cut[j]] = true;
    51         }
    52         tmp[tmpSize++] = arr[i].pos;
    53         dfs(i + 1, i, left - cutSize);
    54         tmpSize--;
    55         for (int j = 0; j < cutSize; j++) {
    56             vis[cut[j]] = false;
    57         }
    58     }
    59 }
    60 int main() {
    61     int T;
    62     int i, j;
    63     scanf("%d", &T);
    64     while (T--) {
    65         scanf("%d%d%d", &n, &m, &w);
    66         for (i = 0; i < n; i++) {
    67             scanf("%d%d", &arr[i].cnt, &arr[i].time);
    68             for (j = 0; j < arr[i].cnt; j++) {
    69                 scanf("%d", &arr[i].fruit[j]);
    70             }
    71             arr[i].pos = i + 1;
    72         }
    73         sort(arr, arr + n);
    74         memset(vis, false, sizeof(vis));
    75         tmpSize = 0;
    76         ansSize = 0;
    77         dfs(0, -1, m);
    78         printf("%d
    ", ansSize);
    79         sort(ans, ans + ansSize);
    80         for (i = 0; i < ansSize; i++) {
    81             printf("%d", ans[i]);
    82             if (i < ansSize - 1) {
    83                 putchar(' ');
    84             } else {
    85                 putchar('
    ');
    86             }
    87         }
    88     }
    89     return 0;
    90 }
    View Code
  • 相关阅读:
    判断具有某个属性js、jQuery
    新建maven项目,JRE System Library[J2SE-1.5]
    maven多模块搭建
    The POM for * is invalid
    【react】react-bookManager
    【cml】wosi-demo
    关于白盒测试
    【weex】h5weex-example
    【weex】publishTask
    Eslint报错的翻译
  • 原文地址:https://www.cnblogs.com/DrunBee/p/3214810.html
Copyright © 2020-2023  润新知