10.5 广州集训 Day4
Posted drizzly
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了10.5 广州集训 Day4相关的知识,希望对你有一定的参考价值。
//为了方便复习先贴上来... 但是NOIP 考前大概没时间订正惹 所以都是留坑T T
摇
【问题背景】
zhx喜欢玩微信摇一摇,著名科学家hys做了一个摇一摇的程序。
【问题描述】
微信摇一摇的原理是,在同一时刻(1s 内)使用摇一摇功能的所用用户,会进入一个名单,系统给每个人返回名单里地理意义上,离你最近的一个(或并列的多个)人。我们假设在某一时刻有 N 个人同时摇动他们的手机,每个人的名字为 Name[i](长度不超过 10,由小写字母组成且无重名)。由于定位服务的精度问 题,第 i 个人的地理坐标只能用两个整数 x[i]和 y[i]粗略的表示(不会有两人在同一个位置),而地理意义的最近表示的是两点之间的直线距离(欧几里得距离) 最短。系统能依次返回每个人配对的对象以及他们之间的距离。 hys 是个忙碌的科学家,你能帮他实现这个小功能吗?
【输入格式】
输入文件第一行为一个整数 N,此后 N 行,每行先是两个整数 x[i]、y[i],然后是一个字符串 Name[i],互相之间用空格隔开。
【输出格式】
共 N 行,每行先输出最近距离,保留两位小数(四舍五入),此后输出离第 i 个人最近的人的名字,若有多个,按字典序从小到大依次输出,中间用空格隔开。
【样例输入】
3
3 0 alice
0 7 bob
-3 0 kitty
【样例输出】
6.00 kitty
7.62 alice kitty
6.00 alice
【数据规模与约定】
对于40%的数据,满足2≤??≤10000。
对于100%的数据, 满足2≤??≤5?10^5,0≤|??i|,|yi|≤1800。
Solution:
留坑
1 #include <cassert> 2 #include <cctype> 3 #include <cstdlib> 4 #include <cstdio> 5 #include <cstring> 6 #include <cmath> 7 #include <ctime> 8 #include <string> 9 #include <complex> 10 #include <numeric> 11 #include <algorithm> 12 #include <functional> 13 #include <utility> 14 #include <vector> 15 #include <stack> 16 #include <queue> 17 #include <deque> 18 #include <bitset> 19 #include <set> 20 #include <map> 21 #include <iterator> 22 #include <iostream> 23 #include <iomanip> 24 #include <sstream> 25 #include <fstream> 26 27 using namespace std; 28 29 const int dx[] = {-1, -1, 1, 1}; 30 const int dy[] = {1, -1, -1, 1}; 31 const int MaxN = 600000; 32 const int MaxM = 4500; 33 const int inf = 1e9; 34 const int OFFSET = 2000; 35 const int THRESHOLD = 5000; 36 typedef complex<int> cpi; 37 38 int n; 39 int x[MaxN], y[MaxN]; 40 char name[MaxN][20]; 41 int grid[MaxM][MaxM]; 42 int vis[MaxM][MaxM]; 43 cpi tc[MaxM*MaxM]; 44 int n_tc; 45 cpi heap[MaxN*64]; 46 int size; 47 int ans[MaxN], ans_size, ans_dis; 48 bool found[MaxN]; 49 50 bool cmp(const cpi &x, const cpi &y) { 51 return norm(x) > norm(y); 52 } 53 bool namecmp(const int &x, const int &y) { 54 return strcmp(name[x], name[y]) < 0; 55 } 56 int dis(int a, int b) { 57 return (x[a]-x[b])*(x[a]-x[b]) + (y[a]-y[b])*(y[a]-y[b]); 58 } 59 60 int main(void) { 61 // freopen("imes.in", "r", stdin); 62 // freopen("imes.out", "w", stdout); 63 64 scanf("%d", &n); 65 for (int i = 1; i <= n; ++i) { 66 scanf("\n%d %d %s", x+i, y+i, name[i]); 67 grid[x[i]+OFFSET][y[i]+OFFSET] = i; 68 } 69 if (n <= THRESHOLD) { 70 for (int i = 1, tmp; i <= n; ++i) { 71 ans_size = 0, ans_dis = inf; 72 for (int j = 1; j <= n; ++j) 73 if (i != j) { 74 tmp = dis(i, j); 75 if (tmp < ans_dis) 76 ans[0] = j, ans_size = 1, ans_dis = tmp; 77 else if (tmp == ans_dis) 78 ans[ans_size++] = j; 79 } 80 sort(ans, ans+ans_size, namecmp); 81 printf("%.2lf", sqrt(double(ans_dis))); 82 for (int j = 0; j < ans_size; ++j) 83 printf(" %s", name[ans[j]]); 84 puts(""); 85 } 86 } else { 87 int __count = 0; 88 for (int i = 1; i <= n; ++i) { 89 for (int j = 0; j < n_tc; ++j) { 90 vis[real(tc[j])][imag(tc[j])] = false; 91 } 92 for (int j = 0; j < ans_size; ++j) 93 found[ans[j]] = false; 94 n_tc = 0; 95 96 size = 0; 97 heap[size++] = cpi(0, 1), heap[size++] = cpi(1, 0); 98 99 int _x = x[i], _y = y[i]; 100 ans_size = 0, ans_dis = inf; 101 while (ans_dis == inf || norm(heap[0]) == ans_dis) { 102 cpi cur = heap[0]; pop_heap(heap, heap+size, cmp); --size; 103 104 for (int k = 0; k < 4; ++k) { 105 int _nx = _x+dx[k]*real(cur), _ny = _y+dy[k]*imag(cur); 106 if (_nx < -OFFSET || _nx > OFFSET || _ny < -OFFSET || _ny > OFFSET) 107 continue; 108 if (grid[_nx+OFFSET][_ny+OFFSET]) { 109 if (ans_dis == inf) 110 ans_dis = norm(cur); 111 if (ans_dis == norm(cur) && !found[grid[_nx+OFFSET][_ny+OFFSET]]) { 112 ans[ans_size++] = grid[_nx+OFFSET][_ny+OFFSET]; 113 found[grid[_nx+OFFSET][_ny+OFFSET]] = true; 114 } 115 } 116 } 117 if (!vis[real(cur)+1][imag(cur)]) heap[size++] = cpi(real(cur)+1, imag(cur)), tc[n_tc++] = heap[size-1], push_heap(heap, heap+size, cmp), vis[real(cur)+1][imag(cur)] = true; 118 if (!vis[real(cur)][imag(cur)+1]) heap[size++] = cpi(real(cur), imag(cur)+1), tc[n_tc++] = heap[size-1], push_heap(heap, heap+size, cmp), vis[real(cur)][imag(cur)+1] = true; 119 __count+=2; 120 } 121 sort(ans, ans+ans_size, namecmp); 122 printf("%.2lf", sqrt(double(ans_dis))); 123 for (int j = 0; j < ans_size; ++j) 124 printf(" %s", name[ans[j]]); 125 puts(""); 126 } 127 // printf("%d\n", __count); 128 } 129 130 return 0; 131 }
变
【问题背景】
zhx和他的妹子玩一个数字游戏。
【问题描述】
zhx手上有 N 个数??3,和另外两个数??和??,满足??>??。
现在,你需要做一 个游戏。游戏中的每一轮中,你可以做如下两种操作之一:
1. 执行??=???1。
2. 选择一个 1 到 N 之间的数 x,执行: ??=???(?? ?????? ??x)
zhx 和他的妹子玩游戏去了,现在,zhx 希望聪明的你告诉他,至少通过多少轮操作,可以使得??= ??。
【输入格式】
第一行一个整数 N。
接下来一行 N 个整数??i。
最后一行两个整数??,??。
【输出格式】
仅一行,包含最少的操作论数
。
【样例输入1】
3
1 2 3
5 2
【样例输出1】
2
【样例输入2】
0
5 2
【样例输出2】
3
【数据规模与约定】
对于30%的数据,满足1≤??≤1000,??≤1000。
对于50%的数据,满足1≤??≤1000,??≤10000。
对于100%的数据, 满足1≤??≤100,0<??<??≤10^7,0<??i≤10^7。
Solution:
留坑。
1 //澶存枃浠秢{{ 2 #include<stdio.h> 3 #include<stdlib.h> 4 #include<string.h> 5 #include<time.h> 6 #include<math.h> 7 #include<algorithm> 8 #include<string> 9 #include<queue> 10 #include<vector> 11 #include<map> 12 #include<set> 13 #include<complex> 14 using namespace std; 15 16 const int inf=0x0f0f0f0f; 17 18 #define uset unordered_set 19 #define umap unordered_map 20 #define pqueue priority_queue 21 22 typedef long long ll; 23 24 typedef pair<int,int> pii; 25 typedef pair<ll,ll> pll; 26 27 typedef complex<double> point; 28 29 typedef vector<int> vint; 30 31 #define pb push_back 32 33 //template<class S,class T> inline pair<S,T> mp(S a,T b){return make_pair(a,b);} 34 #define mp make_pair 35 //template<class S,class T> inline S& LX(pair<S,T> &X){return X.first;} 36 //template<class S,class T> inline const S& LX(const pair<S,T> &X){return X.first;} 37 //template<class S,class T> inline T& RX(pair<S,T> &X){return X.second;} 38 //template<class S,class T> inline const T& RX(const pair<S,T> &X){return X.second;} 39 #define fst first 40 #define snd second 41 42 template<class T> inline void rst(T &a){memset(a,0,sizeof(a));} 43 template<class T> inline void rst1(T &a){memset(a,-1,sizeof(a));} 44 template<class T> inline void sinf(T &a){memset(a,0x0f,sizeof(a));} 45 template<class S,class T> inline void rst(S &a,T b){fill((T*)a,(T*)a+(sizeof(a)/sizeof(b)),b);} 46 template<class T> inline void clr(T &a){a.clear();} 47 template<class S,class T> inline void cpy(S &a,T &b){memcpy(a,b,sizeof(a));} 48 template<class S,class T> inline bool chkmin(S &a,T b){return b<a?a=b,1:0;} 49 template<class S,class T> inline bool chkmax(S &a,T b){return a<b?a=b,1:0;} 50 template<class T> inline T sqr(T x){return x*x;} 51 //template<class T> inline int sz(T &a){return (int)(a.size());} 52 #define sz size 53 //template<class T> inline bool ept(T &a){return a.empty();} 54 #define ept empty 55 //}}} 56 int n; 57 set<int> X; 58 typedef set<int>::iterator iter; 59 int a,b; 60 int noob[100010]; 61 int main(){ 62 scanf("%d",&n); 63 for(int i=1;i<=n;i++){ 64 int x; 65 scanf("%d",&x); 66 X.insert(x); 67 } 68 scanf("%d%d",&a,&b); 69 int ans=0; 70 while(a>b){ 71 int na=a-1; 72 int c=0; 73 for(iter i=X.begin();i!=X.end();++i){ 74 int x=*i; 75 int t=a-a%x; 76 if(t<b)noob[c++]=x; 77 else chkmin(na,t); 78 } 79 for(int i=0;i<c;i++)X.erase(noob[i]); 80 ans++; 81 a=na; 82 } 83 printf("%d\n",ans); 84 return 0; 85 }
搞
【问题背景】
zhx有很多小弟,他突然要搞事情。
【问题描述】
zhx 有很多小弟,编号 2-N(zhx 的编号为 1)。除了 zhx 自己之外,每个人都有一个直接上司,任何消息只能经由一个人的上司传达到他。现在你需要选出一些人(包括 zhx)完成一项任务。除此之外,你需要确定一个人 M(可以不是 被选出的人)作为管理者,且满足他能够给选出的所有人发送指令(直接或间接, 在发送消息时,任何人不管有没有被选出都能帮助传递消息)。 已知让第 i 个人工作需要的薪水为a5,且第 i 个人作为管理者时带来的加成为 b5。假设一共选出了 K 个人,且管理者是 M,那么这个团队的战斗力是K?bI。 现在你希望在选出的人的薪水总和小于等于 C 的情况下,最大化这个战斗力。
【输入格式】
第一行两个整数 N,C。
接下来 N 个每行 3 个整数?? 3,??3,??3,f5表示第 i 个人的上司的编号,a, b 如题意所述 。
输入保证 1 号(zhx)的上司为 0。
【输出格式】
仅一行,可以达到的最大战斗力。
【样例输入】
5 4
0 3 3
1 3 5
2 2 2
1 2 4
2 3 1
【样例输出】
6
【样例解释】
选择 zhx 作为管理者,选择 3,4 号完成任务。
【数据规模与约定】
对于10%的数据,满足1≤ ?? ≤10。
对于40%的数据,满足1≤ ?? ≤10000。
对于100%的数据, 满足1≤ ?? ≤10^5, 0≤??i≤??, 0≤??i,??i,??≤10^9
Solution:
留坑。
1 #include <cstdlib> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 #include <vector> 7 8 typedef long long i64; 9 10 struct vector { 11 vector(void) { 12 v = new int[16]; 13 sz = 0, cap = 16; 14 } 15 void push_back(int x) { 16 if (sz >= cap) realloc(cap * 2); 17 v[sz++] = x; 18 } 19 int pop_back(void) { 20 int ret = v[--sz]; 21 if (sz <= cap / 4 && cap / 2 >= 16) realloc(cap / 2); 22 return ret; 23 } 24 int size(void) { return sz; } 25 int *begin(void) { return v; } 26 int *end(void) { return v + sz; } 27 void realloc(int new_cap) { 28 int *v2 = new int[new_cap]; 29 memcpy(v2, v, sz * sizeof(int)); 30 delete []v; v = v2; 31 cap = new_cap; 32 } 33 int *v, sz, cap; 34 }; 35 36 struct pq { 37 pq(void) {} 38 void push(int x) { 39 v.push_back(x); 40 std::push_heap(v.begin(), v.end()); 41 } 42 int pop() { 43 std::pop_heap(v.begin(), v.end()); 44 return v.pop_back(); 45 } 46 int size() { return v.size(); } 47 vector v; 48 }; 49 50 using std::swap; 51 using std::max; 52 53 const int MaxN = 100005; 54 55 i64 ans; 56 int n, m; 57 int c[MaxN], l[MaxN]; 58 59 struct edge_t { 60 edge_t *next; 61 int a, b; 62 } edges[MaxN]; 63 int nr_edges; 64 65 edge_t *lk[MaxN]; 66 67 void insedge(int a, int b) { 68 edge_t *e = edges + (++nr_edges); 69 e->a = a, e->b = b; 70 e->next = lk[a], lk[a] = e; 71 } 72 73 pq heap[MaxN]; 74 75 void merge(int x, int y) { 76 if (heap[x].size() < heap[y].size()) { 77 swap(heap[x], heap[y]); 78 } 79 80 while (heap[y].size()) { 81 heap[x].push(heap[y].pop()); 82 } 83 } 84 85 int size[MaxN]; 86 i64 sum[MaxN]; 87 88 void dfs(int x) { 89 heap[x].push(c[x]); 90 size[x] = 1, sum[x] = c[x]; 91 for (edge_t *e = lk[x]; e; e = e->next) { 92 dfs(e->b); 93 size[x] += size[e->b], sum[x] += sum[e->b]; 94 merge(x, e->b); 95 } 96 while (sum[x] > m) { 97 size[x]--, sum[x] -= heap[x].pop(); 98 } 99 ans = max(ans, i64(size[x]) * l[x]); 100 } 101 102 int main(void) { 103 freopen("gao.in", "r", stdin); 104 freopen("gao.out", "w", stdout); 105 106 scanf("%d%d", &n, &m); 107 for (int i = 1; i <= n; ++i) { 108 int t; scanf("%d%d%d", &t, c+i, l+i); 109 insedge(t, i); 110 } 111 dfs(1); 112 printf("%lld\n", ans); 113 114 return 0; 115 }
以上是关于10.5 广州集训 Day4的主要内容,如果未能解决你的问题,请参考以下文章