被打日常 20191012
E题一个下午自闭,被吊打是日常的事情,不用奇怪。
刚开始是当成类似灯的开关问题,从左到右把1e9的长度分成最多2*n段然后还特判了一小时,再二分,结果......当然.......TLE
之后看正解,是对特定的点进行差分,把渔夫当成是点,对于每一条鱼的区间加1,然后一次性得到答案
http://codeforces.com/gym/101964/problem/E
1 #include <stdio.h> 2 #include <algorithm> 3 #include <map> 4 using namespace std; 5 const int maxn = 1e9; 6 struct node { 7 int id, flag; 8 }point[200015]; 9 int n, m, l; 10 int x[200015], y[200015], sum[200015], ans[200015]; 11 bool cmp(node a, node b) { 12 return a.flag < b.flag; 13 } 14 struct enode { 15 int p; 16 int id; 17 bool operator < (const enode &a) const{ 18 return p < a.p; 19 } 20 }se[200015]; 21 int tot1 = 1; 22 int cnt = 0; 23 int main() 24 { 25 scanf("%d%d%d", &n, &m, &l); 26 for(int i = 1; i <= n; i++) { 27 scanf("%d%d", &x[i], &y[i]); 28 } 29 for (int i = 1; i <= m; i++) { 30 scanf("%d", &se[i].p); 31 se[i].id = i; 32 } 33 sort(se+1, se+1+m); 34 enode tmp; 35 for (int i = 1; i <= n; i++) { 36 if (y[i] > l) continue; 37 tmp.p = x[i] - (l-y[i]); 38 int p = lower_bound(se+1, se+1+m, tmp) - se; 39 sum[p]++; 40 tmp.p = x[i] + (l-y[i]); 41 p = upper_bound(se+1, se+1+m, tmp) - se; 42 sum[p]--; 43 } 44 for (int i = 1; i <= m; i++) { 45 sum[i] = sum[i] + sum[i-1]; 46 ans[se[i].id] = sum[i]; 47 } 48 for (int i = 1; i <= m; i++) 49 printf("%d\n", ans[i]); 50 return 0; 51 }
C题 最小生成树 有黑白之分, 需求是从n个点中挑出m个点,使得最小生成树最大的黑点连边的最小费用
看别人说最大的最小通常二分,现在枚举lim作为最大连边
最小生成树也是树,bfs序的点被访问到的时候肯定是在被访问到过的点连成的最小生成树的叶结点,从这个点开始dfs以lim作为限制搜索的深度
如果最后搜索到的点数比m多,此时的 lim 大于等于 挑出m个点的最大费用的最小费用
m >= 1 这就意味着有不加边的可能 l = 0,还是wa了
http://codeforces.com/gym/101964/problem/C
#include <stdio.h> #include <string.h> #include <math.h> #include <queue> #include <algorithm> using namespace std; const int maxn = 105; int col[maxn]; int n, m; bool vis[maxn]; struct node{ int v,nxt; }edge[maxn*2]; int tot, head[maxn]; void Insert(int u, int v) { edge[++tot].v = v; edge[tot].nxt = head[u]; head[u] = tot; } int dfs(int u, int fa, int lim, int dis) { int res = col[u]; if (dis >= lim) return res; for (int i = head[u]; i; i = edge[i].nxt) { int v = edge[i].v; if (fa == v || vis[v] == false) continue; res = res + dfs(v, u, lim, dis+1); } return res; } bool check(int lim) { memset(vis, 0, sizeof(vis)); queue <int> q; q.push(1); while (!q.empty()) { int t = q.front();q.pop(); vis[t] = 1; int tt = dfs(t, -1, lim, 0); if (tt >= m) return true; for (int i = head[t]; i; i = edge[i].nxt) { int v = edge[i].v; if (!vis[v]) { q.push(v); } } } return false; } int main() { scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) { scanf("%d", &col[i]); } for (int i = 1; i < n; i++) { int u,v; scanf("%d%d", &u, &v); Insert(u,v); Insert(v,u); } int l = 0, r = n, ans; while (l <= r) { int mid = (l+r)>>1; if (check(mid)) { ans = mid; r = mid-1; } else { l = mid+1; } } printf("%d\n", ans); return 0; }
B题
扣6