HDU 多校联合第二场
1001
不是在为这次比赛找借口。。。我真的想吐嘈一下这道题。。。
尼嘛!明明是状态dp!非得搞得数据随便贪心都能过!!!过你妹啊!埋头想dp的时候,大约开始十几分钟,刷新了一下。我了个去!快上百了!纯属恶心人吗?! 吐嘈完毕 -_-!
状态dp:1 <= N <= 20,最多20位,完全可以位压缩。预处理一下hp_sum[i] (i = 010111...101),表示i的二进制中所有为1的位置,他们的hp之和。 f[i] (i = 010111...101)表示i的二进制中所有为1的位置被干掉话费的最小代价
f[ i|(1<< j) ] = max(f[ i|(1<< j) ], f[i] + hp_sum[ i|(1<<j) ]*p[j].Dpi);
1002
对数据用数状数组预处理,当时根本就没有任何思路。。。任何思路。。。赛后各种水过。。。居然可以蹭数据。。。。枚举出来一个约数,去你妹的!
大概过程是对x,y进行离散话,然后按离散化以后的值作为位置,原值作为value加到数状数组里边。
统计到X时,比X小的数的和为sumx,个数为numx,所以时间为X*numx - sumx。同样,比mx大的数也能统计出来(总数减掉sumx)
同理对Y的在数状数组,也可以得到sumy, numy...
用到四颗数状数组:分别用来计算 sumx, numx, sumy, numy。
#include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <ctime> #include <queue> #include <map> #include <sstream> #define CL(arr, val) memset(arr, val, sizeof(arr)) #define REP(i, n) for((i) = 0; (i) < (n); ++(i)) #define FOR(i, l, h) for((i) = (l); (i) <= (h); ++(i)) #define FORD(i, h, l) for((i) = (h); (i) >= (l); --(i)) #define L(x) (x) << 1 #define R(x) (x) << 1 | 1 #define MID(l, r) (l + r) >> 1 #define Min(x, y) x < y ? x : y #define Max(x, y) x < y ? y : x #define E(x) (1 << (x)) #define iabs(x) ((x) > 0 ? (x) : -(x)) typedef long long LL; const int eps = 1e-8; const LL inf = 1e15; using namespace std; const int N = 100010; struct node { int x; int y; }p[N]; LL cx[N], cy[N]; LL Nx[N], Ny[N]; int tx[N], ty[N], n; int lowbit(int i) { return i&(-i); } void add(LL c[], int i, LL val) { while(i <= n) { c[i] += val; i += lowbit(i); } } LL sum(LL c[], int i) { LL ret = 0; while(i > 0) { ret += c[i]; i -= lowbit(i); } return ret; } int findx(int x) { int l = 1, r = n, mid; while(l <= r) { mid = (l + r) >> 1; if(tx[mid] == x) return mid; else if(tx[mid] < x) l = mid + 1; else r = mid - 1; } return -1; } int findy(int x) { int l = 1, r = n, mid; while(l <= r) { mid = (l + r) >> 1; if(ty[mid] == x) return mid; else if(ty[mid] < x) l = mid + 1; else r = mid - 1; } return -1; } void init() { CL(cx, 0); CL(cy, 0); CL(Nx, 0); CL(Ny, 0); } int main() { //freopen("data.in", "r", stdin); int t, i; int x, y; LL tolx, toly; LL sumx, sumy; LL numx, numy; LL tmpx, tmpy; LL ans; scanf("%d", &t); while(t--) { init(); scanf("%d", &n); ans = inf; tolx = toly = 0; for(i = 1; i <= n; ++i) { scanf("%d%d", tx + i, ty + i); p[i].x = tx[i], p[i].y = ty[i]; tolx += tx[i], toly += ty[i]; } sort(tx + 1, tx + n + 1); sort(ty + 1, ty + n + 1); for(i = 1; i <= n; ++i) { x = findx(p[i].x); y = findy(p[i].y); add(cx, x, p[i].x); add(cy, y, p[i].y); add(Nx, x, 1); add(Ny, y, 1); } //printf("tolx = %lld, toly = %lld\n",tolx,toly); for(i = 1; i <= n; ++i) { x = findx(p[i].x); y = findy(p[i].y); sumx = sum(cx, x) - p[i].x; sumy = sum(cy, y) - p[i].y; numx = sum(Nx, x) - 1; numy = sum(Ny, y) - 1; //printf("sumx = %lld, sumy = %lld, numx = %lld, numy = %lld\n", sumx, sumy, numx, numy); tmpx = (numx*p[i].x - sumx) + (tolx - sumx - p[i].x*(n - numx)); tmpy = (numy*p[i].y - sumy) + (toly - sumy - p[i].y*(n - numy)); //printf("tmpx(%lld) + tmpy(%lld) = %lld\n\n", tmpx, tmpy, tmpx + tmpy); ans = Min(ans, tmpx + tmpy); } cout << ans << endl; } return 0; }
1003
各种蹭数据,真的好无聊。。。标程没看懂
找所有x的中点,所有y的中点,按到中点的距离排序。。。枚举前100个点。这都能蹭过去。。。。
1004
对于这题我只能说我是弱b。。。kruskal改动一下,按边权从大到小排序。。。。并查集维护,要删除的两个点不能在一个集合里边。。。
const int N = 100010; int parent[N]; struct node { int x; int y; int d; } p[N]; int n, k; bool del[N]; bool cmp(node a, node b) { return a.d > b.d; } int find(int x) { int k = x, r = x, j; while(r != parent[r]) { if(del[r]) del[parent[r]] = true; r = parent[r]; } while(k != r) { j = parent[k]; parent[k] = r; k = j; } return r; } LL solve() { LL cnt = 0; int x, y; for(int i = 0; i < n - 1; ++i) { x = find(p[i].x); y = find(p[i].y); if(x == y) continue; if(del[x] && del[y]) {cnt += LL(p[i].d); continue;} parent[y] = x; if(del[y]) del[x] = true; if(del[x]) del[y] = true; } return cnt; } void init() { CL(del, false); for(int i = 0; i <= n; ++i) parent[i] = i; } int main() { //freopen("data.in", "r", stdin); int t, i, x; scanf("%d", &t); while(t--) { scanf("%d%d", &n, &k); init(); for(i = 0; i < n - 1; ++i) { scanf("%d%d%d", &p[i].x, &p[i].y, &p[i].d); } for(i = 0; i < k; ++i) { scanf("%d", &x); del[x] = true; } sort(p, p + n - 1, cmp); cout << solve() << endl; } return 0; }
1009
bfs 爆搞的,记录每个节点的最大剩余电量,防止有环的时候死循环
const int N = 2500010; const int M = 50010; struct node { int to; int next; double val; } g[N]; int head[M], t; double val[M]; void init() { CL(head, -1); t = 0; } void add(int u, int v, double w) { g[t].to = v; g[t].val = w; g[t].next = head[u]; head[u] = t++; } void bfs(int s, double m) { val[s] = m; queue<int> q; q.push(s); int i, u, v; double w; while(!q.empty()) { u = q.front(); q.pop(); for(i = head[u]; i != -1; i = g[i].next) { v = g[i].to; w = val[u]*(100.0 - g[i].val)/100.0; if(w > val[v]) { val[v] = w; q.push(v); } } } } int main() { //freopen("data.in", "r", stdin); int n, t, i, x; double y; while(~scanf("%d", &n)) { init(); for(i = 1; i <= n; ++i) { scanf("%d", &t); while(t--) { scanf("%d%lf", &x, &y); add(i, x, y); } val[i] = -1; } scanf("%d%d%lf", &i, &x, &y); bfs(i, y); if(val[i] == -1) puts("IMPOSSIBLE!"); else printf("%.2f\n", y - val[x]); } return 0; }