hihoCoder挑战赛14 A,B,C题解
转载请注明出处: http://www.cnblogs.com/fraud/ ——by fraud
题目1 : 不等式
描述
给定n个关于X的不等式,问最多有多少个成立。
每个不等式为如下的形式之一:
X < C
X <= C
X = C
X > C
X >= C
输入
第一行一个整数n。
以下n行,每行一个不等式。
数据范围:
1<=N<=50,0<=C<=1000
输出
一行一个整数,表示最多可以同时成立的不等式个数。
- 样例输入
-
4 X = 1 X = 2 X = 3 X > 0
- 样例输出
-
2
枚举所有值,每隔0.5一个,这样就能取到所有情况了。少了小数部分,WA了两下才发现。。。真是惨
1 /** 2 * code generated by JHelper 3 * More info: https://github.com/AlexeyDmitriev/JHelper 4 * @author xyiyy @https://github.com/xyiyy 5 */ 6 7 #include <iostream> 8 #include <fstream> 9 10 //##################### 11 //Author:fraud 12 //Blog: http://www.cnblogs.com/fraud/ 13 //##################### 14 //#pragma comment(linker, "/STACK:102400000,102400000") 15 #include <iostream> 16 #include <sstream> 17 #include <ios> 18 #include <iomanip> 19 #include <functional> 20 #include <algorithm> 21 #include <vector> 22 #include <string> 23 #include <list> 24 #include <queue> 25 #include <deque> 26 #include <stack> 27 #include <set> 28 #include <map> 29 #include <cstdio> 30 #include <cstdlib> 31 #include <cmath> 32 #include <cstring> 33 #include <climits> 34 #include <cctype> 35 36 using namespace std; 37 #define XINF INT_MAX 38 #define INF 0x3FFFFFFF 39 #define mp(X, Y) make_pair(X,Y) 40 #define pb(X) push_back(X) 41 #define rep(X, N) for(int X=0;X<N;X++) 42 #define rep2(X, L, R) for(int X=L;X<=R;X++) 43 #define dep(X, R, L) for(int X=R;X>=L;X--) 44 #define clr(A, X) memset(A,X,sizeof(A)) 45 #define IT iterator 46 #define ALL(X) (X).begin(),(X).end() 47 #define PQ std::priority_queue 48 typedef long long ll; 49 typedef unsigned long long ull; 50 typedef pair<int, int> PII; 51 typedef vector<PII> VII; 52 typedef vector<int> VI; 53 54 int getTheAnswer() { 55 return 42; 56 } 57 58 char a[110]; 59 string str[110]; 60 double num[110]; 61 62 class TaskA { 63 public: 64 void solve(std::istream &in, std::ostream &out) { 65 int n; 66 while (in >> n) { 67 rep(i, n) 68 in >> a[i] >> str[i] >> num[i]; 69 int ans = 0; 70 for (double i = -1.5; i < 1010; i += 1.0) { 71 int m = 0; 72 rep(j, n) { 73 if (gao(i, j))m++; 74 } 75 ans = max(ans, m); 76 } 77 rep2(i, -10, 1010) { 78 int m = 0; 79 rep(j, n) { 80 if (gao(i, j))m++; 81 } 82 ans = max(ans, m); 83 } 84 out << ans << endl; 85 86 } 87 } 88 89 bool gao(double x, int i) { 90 if (str[i] == "<") { 91 return x < num[i]; 92 } else if (str[i] == "<=") { 93 return x <= num[i]; 94 } else if (str[i] == "=") { 95 return x == num[i]; 96 } else if (str[i] == ">") { 97 return x > num[i]; 98 } else if (str[i] == ">=") { 99 return x >= num[i]; 100 } 101 } 102 }; 103 104 int main() { 105 std::ios::sync_with_stdio(false); 106 std::cin.tie(0); 107 TaskA solver; 108 std::istream &in(std::cin); 109 std::ostream &out(std::cout); 110 solver.solve(in, out); 111 return 0; 112 }
题目2 : 赛车
描述
幻想乡有一个赛车场。赛车场里有N个地点。同时地点之间还有单向的道路存在。
这些道路使得赛车场形成了一个外向树的结构。也就是说,道路将这N个地点连成了一个有根树。并且所有的边都是从父亲指向孩子的。
由于幽香喜欢刺激,每次她去赛车场都会从根节点出发,选择最长的一条路径来玩。
但是现在幽香感觉最长的路径还是太短了,她打算在赛车场里新建一条道路使得新的最长路径最长。
同时,如果道路形成了一个环,那么可能会出现交通事故,所以幽香新建的道路不能导致环的出现。
你能帮幽香算出新建一条道路后的最长路径吗?幽香知道根节点一定是1号点。
输入
一行一个数N,表示地点的数量。
接下来N-1行,每行两个数a和b,表示从点a到点b有一条单向路径。所有点从1到n标号。
数据范围:
n<=100000。
输出
一行表示新建一条边后的最长路径。
- 样例输入
-
5 1 2 2 3 1 4 4 5
- 样例输出
-
4
树形DP裸题,先dfs处理一下,然后枚举所有点,求出从根节点出发到这个点的路径长度,以及这个点往下的最长路以及次长路即可。
1 /** 2 * code generated by JHelper 3 * More info: https://github.com/AlexeyDmitriev/JHelper 4 * @author xyiyy @https://github.com/xyiyy 5 */ 6 7 #include <iostream> 8 #include <fstream> 9 10 //##################### 11 //Author:fraud 12 //Blog: http://www.cnblogs.com/fraud/ 13 //##################### 14 //#pragma comment(linker, "/STACK:102400000,102400000") 15 #include <iostream> 16 #include <sstream> 17 #include <ios> 18 #include <iomanip> 19 #include <functional> 20 #include <algorithm> 21 #include <vector> 22 #include <string> 23 #include <list> 24 #include <queue> 25 #include <deque> 26 #include <stack> 27 #include <set> 28 #include <map> 29 #include <cstdio> 30 #include <cstdlib> 31 #include <cmath> 32 #include <cstring> 33 #include <climits> 34 #include <cctype> 35 36 using namespace std; 37 #define XINF INT_MAX 38 #define INF 0x3FFFFFFF 39 #define mp(X, Y) make_pair(X,Y) 40 #define pb(X) push_back(X) 41 #define rep(X, N) for(int X=0;X<N;X++) 42 #define rep2(X, L, R) for(int X=L;X<=R;X++) 43 #define dep(X, R, L) for(int X=R;X>=L;X--) 44 #define clr(A, X) memset(A,X,sizeof(A)) 45 #define IT iterator 46 #define ALL(X) (X).begin(),(X).end() 47 #define PQ std::priority_queue 48 typedef long long ll; 49 typedef unsigned long long ull; 50 typedef pair<int, int> PII; 51 typedef vector<PII> VII; 52 typedef vector<int> VI; 53 54 int getTheAnswer() { 55 return 42; 56 } 57 58 vector<int> G[100010]; 59 int dp[100010][2]; 60 int pre[100010][2]; 61 int dep[100010]; 62 int ans; 63 64 class TaskB { 65 public: 66 void solve() { 67 int n; 68 while (scanf("%d",&n)!=EOF) { 69 rep(i, n)G[i].clear(); 70 int u, v; 71 rep(i, n - 1) { 72 scanf("%d%d",&u,&v);//in >> u >> v; 73 u--; 74 v--; 75 G[u].pb(v); 76 } 77 dep[0] = 0; 78 dfs(0, -1); 79 ans = 0; 80 dfs2(0, -1); 81 printf("%d\n",ans);//out << ans << endl; 82 } 83 } 84 85 void dfs(int u, int fa) { 86 dp[u][0] = dp[u][1] = 0; 87 pre[u][0] = pre[u][1] = -1; 88 int sz = G[u].size(); 89 rep(i, sz) { 90 int v = G[u][i]; 91 dep[v] = dep[u] + 1; 92 dfs(v, u); 93 if (dp[v][0] + 1 > dp[u][1]) { 94 dp[u][1] = dp[v][0] + 1; 95 pre[u][1] = v; 96 if (dp[u][1] > dp[u][0]) { 97 swap(dp[u][1], dp[u][0]); 98 swap(pre[u][1], pre[u][0]); 99 } 100 } 101 } 102 } 103 104 void dfs2(int u, int fa) { 105 int sz = G[u].size(); 106 rep(i, sz) { 107 int v = G[u][i]; 108 ans = max(ans, dp[u][1] + dep[u] + dp[u][0]); 109 dfs2(v, u); 110 } 111 } 112 }; 113 114 int main() { 115 TaskB solver; 116 solver.solve(); 117 return 0; 118 }
题目3 : 向日葵
描述
幽香打算种一些向日葵,让自己的太阳花田更加的漂亮。
现在太阳花田上什么植物都没有。幽香搞到了一些向日葵的种子。不过幽香觉得如果直接种的话太无趣了,
她打算采取一种比较有趣的种法。
她在太阳花田上选择了n对点,分别为(a1,b1),(a2,b2),...,(an,bn)。然后对于每一对点(ai,bi),她会以一半的概率在ai种一个向日葵,一半的概率在bi种一个向日葵。
种完向日葵以后,幽香需要将这些向日葵围起来建成花园。防止被其它小妖精踩踏。花园可以看成就是这些种了的向日葵的凸包。那么幽香想知道花园的期望大小是多少呢?
输入
第一行n,表示点对的个数。
接下来n行,每行4个数,第i行前两个数为ai的x,y坐标,后两个数为bi的x,y坐标。
数据范围:
n<=1000。
所有坐标都是绝对值小于1e9的整数。
输入中的2n个点不存在3点共线,或者2点重合的情况。
输出
一行答案。相对误差在1e-6以内就算正确。
- 样例输入
-
10 703 548 811 701 978 368 435 32 270 667 550 68 326 486 217 486 116 344 361 418 591 563 38 373 548 210 94 800 978 1000 169 278 362 32 899 331 401 339 399 334
- 样例输出
-
407253.2333984375
比赛的时候一直没想通每条边在凸包出现的概率怎么算。
因为边的概率其实就是有向三角形的概率,而所有有向三角形面积的和就是凸包的面积。
先枚举所有边,然后再枚举所有点,对于每个点, 看在其左边和右边的的可能性,那么其概率就是两个点中叉积小于0的概率,因为小于0的点才是在凸包内的,这样枚举的那条边才会对面积做出贡献。
1 /** 2 * code generated by JHelper 3 * More info: https://github.com/AlexeyDmitriev/JHelper 4 * @author xyiyy @https://github.com/xyiyy 5 */ 6 7 #include <iostream> 8 #include <fstream> 9 10 //##################### 11 //Author:fraud 12 //Blog: http://www.cnblogs.com/fraud/ 13 //##################### 14 //#pragma comment(linker, "/STACK:102400000,102400000") 15 #include <iostream> 16 #include <sstream> 17 #include <ios> 18 #include <iomanip> 19 #include <functional> 20 #include <algorithm> 21 #include <vector> 22 #include <string> 23 #include <list> 24 #include <queue> 25 #include <deque> 26 #include <stack> 27 #include <set> 28 #include <map> 29 #include <cstdio> 30 #include <cstdlib> 31 #include <cmath> 32 #include <cstring> 33 #include <climits> 34 #include <cctype> 35 36 using namespace std; 37 #define XINF INT_MAX 38 #define INF 0x3FFFFFFF 39 #define mp(X, Y) make_pair(X,Y) 40 #define pb(X) push_back(X) 41 #define rep(X, N) for(int X=0;X<N;X++) 42 #define rep2(X, L, R) for(int X=L;X<=R;X++) 43 #define dep(X, R, L) for(int X=R;X>=L;X--) 44 #define clr(A, X) memset(A,X,sizeof(A)) 45 #define IT iterator 46 #define ALL(X) (X).begin(),(X).end() 47 #define PQ std::priority_queue 48 typedef long long ll; 49 typedef unsigned long long ull; 50 typedef pair<int, int> PII; 51 typedef vector<PII> VII; 52 typedef vector<int> VI; 53 54 int getTheAnswer() { 55 return 42; 56 } 57 // 58 // Created by xyiyy on 2015/8/10. 59 // 60 61 #ifndef ICPC_P_HPP 62 #define ICPC_P_HPP 63 64 const double EPS = 1e-10; 65 66 int sig(double x) { 67 if (fabs(x) < EPS)return 0; 68 return x < 0 ? -1 : 1; 69 } 70 71 double add(double a, double b) { 72 if (fabs(a + b) < EPS * (fabs(a) + fabs(b)))return 0; 73 return a + b; 74 } 75 76 class P { 77 public: 78 double x, y; 79 80 P() { } 81 82 P(double x, double y) : x(x), y(y) { } 83 84 P operator+(const P &p) { 85 return P(add(x, p.x), add(y, p.y)); 86 } 87 88 P operator-(const P &p) { 89 return P(add(x, -p.x), add(y, -p.y)); 90 } 91 92 P operator*(const double &d) { 93 return P(x * d, y * d); 94 } 95 96 P operator/(const double &d) { 97 return P(x / d, y / d); 98 } 99 100 double Dot(P p) { 101 return x * p.x + y * p.y; 102 } 103 104 double dot(P p) { 105 return add(x * p.x, y * p.y); 106 } 107 108 double Det(P p) { 109 return x * p.y - y * p.x; 110 } 111 112 double det(P p) { 113 return add(x * p.y, -y * p.x); 114 } 115 116 117 double abs() { 118 return sqrt(abs2()); 119 } 120 121 double abs2() { 122 return dot(*this); 123 } 124 125 //绕原点旋转角度B(弧度值)产生新的点 126 P rot(double rad) { 127 return P(add(x * cos(rad), -y * sin(rad)), add(x * sin(rad), y * cos(rad))); 128 } 129 130 P rot90() { 131 return P(-y, x); 132 } 133 134 bool equals(P p) { 135 return compareTo(p) == 0; 136 } 137 138 int compareTo(P p) { 139 int b = sig(x - p.x); 140 if (b != 0)return b; 141 return sig(y - p.y); 142 } 143 144 }; 145 146 147 //判断点是否在线段上 148 bool on_seg(P p1, P p2, P q) { 149 return (p1 - q).det(p2 - q) == 0 && (p1 - q).dot(p2 - q) <= 0; 150 } 151 152 //求两条线段的交点 153 P intersection(P p1, P p2, P q1, P q2) { 154 return p1 + (p2 - p1) * ((q2 - q1).det(q1 - p1) / (q2 - q1).det(p2 - p1)); 155 } 156 157 //线段相交判定 158 bool crsSS(P p1, P p2, P q1, P q2) { 159 if (max(p1.x, p2.x) + EPS < min(q1.x, q2.x))return false; 160 if (max(q1.x, q2.x) + EPS < min(p1.x, p2.x))return false; 161 if (max(p1.y, p2.y) + EPS < min(q1.y, q2.y))return false; 162 if (max(q1.y, q2.y) + EPS < min(p1.y, p2.y))return false; 163 /*(if((p1 - p2).det(q1 - q2) == 0){ 164 return (on_seg(p1,p2,q1) || on_seg(p1,p2,q2) || on_seg(q1,q2,p1) || on_seg(q1,q2,p2)); 165 }else{ 166 P r = intersection(p1,p2,q1,q2); 167 return on_seg(p1,p2,r) && on_seg(q1,q2,r); 168 169 }*/ 170 return (p2 - p1).det(q1 - p1) * (p2 - p1).det(q2 - p1) <= 0 171 && (q2 - q1).det(p1 - q1) * (q2 - q1).det(p2 - q1) <= 0; 172 } 173 174 //直线和线段相交判断 175 bool crsLS(P l1, P l2, P s1, P s2) { 176 return (s1 - l2).det(l1 - l2) * (s2 - l2).det(l1 - l2) <= 0; 177 } 178 179 //直线相交判断 180 //返回-1表示重合,0表示平行,1表示相交 181 int crsLL(P p1, P p2, P q1, P q2) { 182 if (sig((p1 - p2).det(q1 - q2)) != 0)return 1; 183 if (sig((p1 - q2).det(q1 - p2)) != 0)return 0; 184 return -1; 185 } 186 187 //直线和直线的交点 188 /*P isLL(P p1,P p2,P q1,P q2){ 189 double d = (q2 - q1).det(p2 - p1); 190 if(sig(d)==0)return NULL; 191 return intersection(p1,p2,q1,q2); 192 }*/ 193 194 //点到直线的垂足 195 P proj(P p1, P p2, P q) { 196 return p1 + ((p2 - p1) * ((p2 - p1).dot(q - p1) / (p2 - p1).abs2())); 197 } 198 199 //直线到点的距离 200 double disLP(P p1, P p2, P q) { 201 return fabs((p2 - p1).det(q - p1)) / (p2 - p1).abs(); 202 } 203 204 205 //线段到点的距离 206 double disSP(P p1, P p2, P q) { 207 if ((p2 - p1).dot(q - p1) <= 0)return (q - p1).abs(); 208 if ((p1 - p2).dot(q - p2) <= 0)return (q - p2).abs(); 209 return disLP(p1, p2, q); 210 } 211 212 //圆和线段相交的判定 213 bool crsCS(P c, double r, P p1, P p2) { 214 return disSP(p1, p2, c) < r + EPS && (r < (c - p1).abs() + EPS || r < (c - p2).abs() + EPS); 215 } 216 217 //圆与圆相交的判定 218 bool crsCC(P c1, double r1, P c2, double r2) { 219 double dis = (c1 - c2).abs(); 220 return dis < r1 + r2 + EPS && fabs(r1 - r2) < dis + EPS; 221 } 222 223 //四点共圆判定 224 /*bool onC(P p1,P p2,P p3,P p4){ 225 P c = CCenter(p1,p2,p3); 226 if(c == NULL) return false; 227 return add((c - p1).abs2(), -(c - p4).abs2()) == 0; 228 }*/ 229 230 //三点共圆的圆心 231 /*P CCenter(P p1,P p2,P p3){ 232 //if(disLP(p1, p2, p3) < EPS)return NULL;//三点共线 233 P q1 = (p1 + p2) * 0.5; 234 P q2 = q1 + ((p1 - p2).rot90()); 235 P s1 = (p3 + p2) * 0.5; 236 P s2 = s1 + ((p3 - p2).rot90()); 237 return isLL(q1,q2,s1,s2); 238 }*/ 239 240 //求两圆的极角 以p为中心 241 double polarangle(P p, P q) { 242 return atan2(q.y - p.y, q.x - p.x); 243 } 244 245 246 bool cmp_x(const P &p, const P &q) { 247 if (p.x != q.x) return p.x < q.x; 248 return p.y < q.y; 249 } 250 251 vector<P> qs; 252 253 void convex_hull(P *ps, int n) { 254 sort(ps, ps + n, cmp_x); 255 int k = 0; 256 qs.resize(2 * n); 257 for (int i = 0; i < n; qs[k++] = ps[i++]) { 258 while (k > 1 && (qs[k - 1] - qs[k - 2]).det(ps[i] - qs[k - 1]) < EPS)k--; 259 } 260 for (int i = n - 2, t = k; i >= 0; qs[k++] = ps[i--]) { 261 while (k > t && (qs[k - 1] - qs[k - 2]).det(ps[i] - qs[k - 1]) < EPS)k--; 262 } 263 qs.resize(k - 1); 264 } 265 266 //求凸包的直径 267 double convexDiameter() { 268 int qsz = qs.size(); 269 if (qsz == 1)return 0; 270 if (qsz == 2) { 271 return (qs[0] - qs[1]).abs(); 272 } 273 int i = 0, j = 0; 274 rep(k, qsz) { 275 if (!cmp_x(qs[i], qs[k]))i = k; 276 if (cmp_x(qs[j], qs[k])) j = k; 277 } 278 double res = 0; 279 int si = i, sj = j; 280 while (i != sj || j != si) { 281 res = max(res, (qs[i] - qs[j]).abs()); 282 if ((qs[(i + 1) % qsz] - qs[i]).det(qs[(j + 1) % qsz] - qs[j]) < 0) i = (i + 1) % qsz; 283 else j = (j + 1) % qsz; 284 } 285 return res; 286 } 287 288 289 #endif //ICPC_P_HPP 290 291 P p[1010][2]; 292 293 class TaskC { 294 public: 295 void solve(std::istream &in, std::ostream &out) { 296 int n; 297 in >> n; 298 rep(i, n) 299 rep(j, 2)in >> p[i][j].x >> p[i][j].y; 300 double ans = 0; 301 rep(i, n) 302 rep(l1, 2) { 303 P p1 = p[i][l1]; 304 rep(j, n) { 305 if (i == j)continue; 306 rep(l2, 2) { 307 P p2 = p[j][l2]; 308 double sum = p1.Det(p2) * 0.125; 309 p2 = p2 - p1; 310 rep(k, n) { 311 if (i == k || j == k)continue; 312 if (sig(sum) == 0)break; 313 int num = 0; 314 rep(l3, 2) { 315 if (p2.Det(p[k][l3] - p1) > 0); 316 else num++; 317 } 318 sum *= num/2.0; 319 } 320 ans += sum; 321 } 322 } 323 } 324 out << fixed << setprecision(10) << fabs(ans) << endl; 325 } 326 }; 327 328 int main() { 329 std::ios::sync_with_stdio(false); 330 std::cin.tie(0); 331 TaskC solver; 332 std::istream &in(std::cin); 333 std::ostream &out(std::cout); 334 solver.solve(in, out); 335 return 0; 336 }
当然,对于这题你也可以对于每个点先求出所有点的极角,排个序然后来做。这样就可以从O(n^3)变成O(n^2logn)了
还剩下D题还是不会做,待以后再补