【 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\n", 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\n", x, y);

105                     cover(x, y, 1, 0, n - 1, 1);

106                 }

107             } else {

108                 printf("%d\n", sum(a, b, 0, n - 1, 1));

109                 cover(a, b, 0, 0, n - 1, 1);

110             }

111         }

112         putchar('\n');

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\n", 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\n", 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\n", 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\n", 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\n", 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('\n');

86             }

87         }

88     }

89     return 0;

90 }
View Code

 

你可能感兴趣的:(test)