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

 

posted on 2013-07-29 23:07  DrunBee  阅读(740)  评论(0编辑  收藏  举报