标签:
题目链接:点击打开链接
ZOJ 3573 Under Attack
距离做这套题到写题解间隔比较久,题意有些忘了。。
#include <iostream> #include <cstdio> #include <algorithm> #include <string> #include <cmath> #include <cstring> #include <queue> #include <set> #include <map> #include <vector> using namespace std; typedef long long ll; const int N = 15005; int sum[N], a[N]; template <class T> inline bool rd(T &ret) { char c; int sgn; if(c=getchar(),c==EOF) return 0; while(c!='-'&&(c<'0'||c>'9')) c=getchar(); sgn=(c=='-')?-1:1; ret=(c=='-')?0:(c-'0'); while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0'); ret*=sgn; return 1; } template <class T> inline void pt(T x) { if (x <0) { putchar('-'); x = -x; } if(x>9) pt(x/10); putchar(x%10+'0'); } int main() { int n; while(~scanf("%d", &n)) { memset(a, 0, sizeof a); memset(sum, 0, sizeof sum); int l, r, d; while(true) { rd(l); rd(r); rd(d); if(l == -1) break; a[l] += d; a[r+1] -= d; } int L = 0, R = 0; sum[0] = a[0]; for(int i = 1; i <= n; i ++) { sum[i] = sum[i-1] + a[i]; // printf("%d ", sum[i]); if(sum[i] > sum[L]) L = i; if(sum[i] >= sum[R]) R = i; } printf("%d %d\n", L, R); } return 0; }
题目链接:点击打开链接
ZOJ 3574 Under Attack II
题意:
第一行输入a,b
第二行输入k对数字表示k条直线的点斜式
给定二维平面的一个区域 [a,b],用k条直线分割此平面,问分割成多少块(一个点至多被2条直线经过)
思路:
对于一条直线我们能求出这条直线与 x=a , x=b 的两个交点。
当我们插入一条直线时能增加的平面个数就是这条直线下方 x=a 与先前的直线交点个数- x=b与先前的直线交点个数的差的绝对值。
维护两个树状数组来记录x=a和x=b的交点个数
#include <cstdio> #include <vector> #include <algorithm> #include <iostream> #include <map> #include <set> #include <queue> #include <cstring> #include <cmath> #include <string> using namespace std; const int inf = 1e9; const int mod = 1e9+7; const int MAXN = 30010; template <class T> inline bool rd(T &ret) { char c; int sgn; if (c = getchar(), c == EOF) return 0; while (c != '-' && (c<'0' || c>'9')) c = getchar(); sgn = (c == '-') ? -1 : 1; ret = (c == '-') ? 0 : (c - '0'); while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0'); ret *= sgn; return 1; } template <class T> inline void pt(T x) { if (x <0) { putchar('-'); x = -x; } if (x>9) pt(x / 10); putchar(x % 10 + '0'); } typedef long long ll; struct Tree{ int c[30000*3+10], maxn; void init(int x){ maxn = x+10; memset(c, 0, sizeof c); } inline int Lowbit(int x){ return x&(-x); } void change(int i, int x)//i点增量为x { while (i <= maxn) { c[i] += x; i += Lowbit(i); } } int sum(int x){//区间求和 [1,x] int ans = 0; for (int i = x; i >= 1; i -= Lowbit(i)) ans += c[i]; return ans; } }t[2]; struct node{ int k, b, y1, y2; node(){} node(int a, int y):k(a), b(y){} }a[MAXN]; int l, r, n; vector<int>G; int main() { while (~scanf("%d %d", &l, &r)) { G.clear(); rd(n); for (int i = 1, k, b; i <= n; i++){ rd(k); rd(b); a[i] = node(k, b); a[i].y1 = k*l + b; a[i].y2 = k*r + b; G.push_back(a[i].y1); G.push_back(a[i].y2); } G.push_back(G[0] - 1); sort(G.begin(), G.end()); G.erase(unique(G.begin(), G.end()), G.end()); for (int i = 1; i <= n; i++){ a[i].y1 = lower_bound(G.begin(), G.end(), a[i].y1) - G.begin() + 1; a[i].y2 = lower_bound(G.begin(), G.end(), a[i].y2) - G.begin() + 1; } t[0].init(G.size()); t[1].init(G.size()); int ans = 1; for (int i = 1; i <= n; i++){ int x = t[0].sum(a[i].y1 - 1), y = t[1].sum(a[i].y2 - 1); ans += abs(x - y) + 1; t[0].change(a[i].y1, 1); t[1].change(a[i].y2, 1); } pt(ans); putchar('\n'); } return 0; }
题目链接:点击打开链接
ZOJ 3575 Under Attack
给定一个椭圆,问最多能覆盖平面上多少个点。
思路:枚举任意两个点就能确定一个椭圆的2个圆心。然后判断这个圆心的覆盖点数,取最大值即可。
#include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; const int MAX_N = 207; const double eps = 1e-7; struct Point { double x, y; Point () { } Point (double _x, double _y) { x = _x, y = _y; } Point operator + (Point rhs) { return Point(x + rhs.x, y + rhs.y); } Point operator - (Point rhs) { return Point(x - rhs.x, y - rhs.y); } Point operator * (double t) { return Point(x * t, y * t); } double len() { return sqrt(x * x + y * y); } Point turn(double rad) { return Point(x * rad / len(), y * rad / len()); } }; double a, b; int n; Point p[MAX_N]; double dis(int i, int j) { // printf("%f %f\n", (p[i] - p[j]).x, (p[i] - p[j]).y); return (p[i] - p[j]).len(); } int get(Point o) { int cnt = 0; for (int i = 0; i < n; ++i) { double l = (p[i] - o).len(); // printf("qqqqqqq %f %f %f\n", o.x, o.y, l); if (l - a < eps) ++cnt; } return cnt; } int main() { while (2 == scanf("%lf%lf", &a, &b)) { scanf("%d", &n); for (int i = 0; i < n; ++i) { scanf("%lf%lf", &p[i].x, &p[i].y); p[i].y *= a / b; } if(n == 0 || fabs(a) < eps || fabs(b) < eps) { printf("0\n"); continue; } int ans = 1; for (int i = 0; i < n; ++i) { // printf("%lf %lf", p[i].x, p[i].y); for (int j = i + 1; j < n; ++j) { double d = dis(i, j); if (2 * a - d < -eps) continue; Point o = (p[i] + p[j]) * 0.5; double l = sqrt(a * a - d * d / 4); Point F = Point(-(p[i] - p[j]).y, (p[i] - p[j]).x); // printf("zzzzzzzzzz %f %f %f %f\n", F.x, F.y, o.x, o.y); Point up = o + F.turn(l); Point down = o - F.turn(l); ans = max(ans, get(up)); ans = max(ans, get(down)); } } printf("%d\n", ans); } return 0; }
题目链接:点击打开链接
zoj 3576 Count the Length
题意:
给定n*m的方格,左下角为红色,红蓝相间绘制的矩阵,问副对角线的长度。
#include <cstdio> #include <vector> #include <algorithm> #include <iostream> #include <map> #include <set> #include <queue> #include <cstring> #include <cmath> #include <string> using namespace std; const int inf = 1e9; const int mod = 10007; const int MAXN = 305; template <class T> inline bool rd(T &ret) { char c; int sgn; if (c = getchar(), c == EOF) return 0; while (c != '-' && (c<'0' || c>'9')) c = getchar(); sgn = (c == '-') ? -1 : 1; ret = (c == '-') ? 0 : (c - '0'); while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0'); ret *= sgn; return 1; } template <class T> inline void pt(T x) { if (x <0) { putchar('-'); x = -x; } if (x>9) pt(x / 10); putchar(x % 10 + '0'); } typedef long long ll; ll n, m; ll gcd(ll a, ll b) { while(a > 0 && b > 0) { if(a > b) a %= b; else b %= a; } return a+b; } int main() { while(~scanf("%lld%lld", &n, &m)) { double ans = sqrt((double)n*n+m*m); if(n%2==0&&m%2==0) { ans /= 2.0; } else { int g = gcd(n, m); n /= g; m/= g; double d = (double)(n*m+1) / (double)(n*m*2); ans *= d; } printf("%.3f\n", ans); } return 0; }题目链接:点击打开链接
zoj 3578 Matrix
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int MAX_N = 1007; struct Node { int x, y, ax, ay, h; Node () { } Node (int _x, int _y, int _ax, int _ay, int _h) { x = _x, y = _y; ax = _ax, ay = _ay; h = _h; } }; int N, M, C; Node mat[MAX_N]; bool cross2(int i,int j){ if(mat[i].x >= mat[j].ax||mat[j].x >= mat[i].ax) return false; if(mat[i].y >= mat[j].ay||mat[j].y >= mat[i].ay) return false; return true; } bool cross(int i, int j) { int a[4][2]; a[0][0] = mat[i].x, a[0][1] = mat[i].y; a[1][0] = mat[i].x, a[1][1] = mat[i].ay; a[2][0] = mat[i].ax, a[2][1] = mat[i].y; a[3][0] = mat[i].ax, a[3][1] = mat[i].ay; for (int ii = 0; ii < 4; ++ii) { if (mat[j].x <= a[ii][0] && a[ii][0] <= mat[j].ax && mat[j].y <= a[ii][1] && a[ii][1] <= mat[j].ay) return true; } return false; } int main() { while (3 == scanf("%d%d%d", &N, &M, &C)) { memset(mat, 0, sizeof mat); for (int i = 1; i <= C; ++i) { int x, y, a, b, h; scanf("%d%d%d%d%d", &a, &b, &h, &x, &y); mat[i] = Node (x, y, x + a, y + b, 0); int now = 0; for (int j = 1; j < i; ++j) { if (cross2(i, j)) { now = max(now, mat[j].h); } } mat[i].h = now + h; } int ans = 0; for (int i = 1; i <= C; ++i) { //printf("%d %d %d %d %d\n", mat[i].x, mat[i].y, mat[i].ax, mat[i].ay, mat[i].h); ans = max(ans, mat[i].h); } printf("%d\n", ans); } return 0; }
ZOJ Monthly,Feburary 2012 部分题解
标签:
原文地址:http://blog.csdn.net/qq574857122/article/details/43605261