我主看C和F
C题就是一个套板子题
题意
求圆与矩形的相交面积
把圆和凸包相交面积板子套上即可
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<vector>
#include<set>
#include<map>
#include<numeric>
#include<deque>
using namespace std;
typedef long long ll;
#define inf 1000000000000
#define M 100009
#define eps 1e-12
#define PI acos(-1.0)
struct Point
{
double x, y;
Point() {}
Point(double xx, double yy) {x = xx; y = yy;}
Point operator -(Point s) {return Point(x - s.x, y - s.y);}
Point operator +(Point s) {return Point(x + s.x, y + s.y);}
double operator *(Point s) {return x * s.x + y * s.y;}
double operator ^(Point s) {return x * s.y - y * s.x;}
} p[M];
double max(double a, double b) {return a > b ? a : b;}
double min(double a, double b) {return a < b ? a : b;}
double len(Point a) {return sqrt(a * a);}
double dis(Point a, Point b) {return len(b - a);} //两点之间的距离
double cross(Point a, Point b, Point c) //叉乘
{
return (b - a) ^ (c - a);
}
double dot(Point a, Point b, Point c) //点乘
{
return (b - a) * (c - a);
}
int judge(Point a, Point b, Point c) //判断c是否在ab线段上(前提是c在直线ab上)
{
if (c.x >= min(a.x, b.x)
&& c.x <= max(a.x, b.x)
&& c.y >= min(a.y, b.y)
&& c.y <= max(a.y, b.y)) return 1;
return 0;
}
double area(Point b, Point c, double r)
{
Point a(0.0, 0.0);
if (dis(b, c) < eps) return 0.0;
double h = fabs(cross(a, b, c)) / dis(b, c);
if (dis(a, b) > r - eps && dis(a, c) > r - eps) //两个端点都在圆的外面则分为两种情况
{
double angle = acos(dot(a, b, c) / dis(a, b) / dis(a, c));
if (h > r - eps) return 0.5 * r * r * angle; else if (dot(b, a, c) > 0 && dot(c, a, b) > 0)
{
double angle1 = 2 * acos(h / r);
return 0.5 * r * r * fabs(angle - angle1) + 0.5 * r * r * sin(angle1);
} else return 0.5 * r * r * angle;
} else if (dis(a, b) < r + eps && dis(a, c) < r + eps) return 0.5 * fabs(cross(a, b, c)); //两个端点都在圆内的情况
else//一个端点在圆上一个端点在圆内的情况
{
if (dis(a, b) > dis(a, c)) swap(b, c); //默认b在圆内
if (fabs(dis(a, b)) < eps) return 0.0; //ab距离为0直接返回0
if (dot(b, a, c) < eps)
{
double angle1 = acos(h / dis(a, b));
double angle2 = acos(h / r) - angle1;
double angle3 = acos(h / dis(a, c)) - acos(h / r);
return 0.5 * dis(a, b) * r * sin(angle2) + 0.5 * r * r * angle3;
} else
{
double angle1 = acos(h / dis(a, b));
double angle2 = acos(h / r);
double angle3 = acos(h / dis(a, c)) - angle2;
return 0.5 * r * dis(a, b) * sin(angle1 + angle2) + 0.5 * r * r * angle3;
}
}
}//圆与凸多边形相交面积
int main()
{
double x, y, r;
scanf("%lf%lf%lf%lf%lf%lf%lf",&x,&y,&r,&p[1].x,&p[1].y,&p[3].x,&p[3].y);
p[2].y = p[1].y;
p[2].x = p[3].x;
p[4].y = p[3].y;
p[4].x = p[1].x;
p[5] = p[1];
Point o(x, y);
for (int i = 1; i <= 5; i++)
{
p[i] = p[i] - o;
}
double ans = 0;
for (int i = 1; i <= 4; i++)
{
double ss = area(p[i], p[i + 1], r);
if (cross(Point(0, 0), p[i], p[i + 1]) > 0)
ans += ss;
else
ans -= ss;
}
printf("%.4f\n",fabs(ans));
return 0;
}
F题类似与三分,但三分是严格单调的,前期用三分一直wa,才发现这个问题,于是设置一个三分次数的限制即可。
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<vector>
#include<set>
#include<map>
#include<numeric>
#include<deque>
#include<queue>
#include<sstream>
using namespace std;
typedef long long ll;
const ll linf = 0x3f3f3f3f3f3f3f3f;
ll n, k;
ll x[1000005];
ll f(ll d)
{
ll ans = 0;
ll D = d;
for (int i = 0; i < n; i++)
{
ans += abs(D - x[i]);
D += k;
}
return ans;
}
int main()
{
scanf("%lld%lld", &n, &k);
for (int i = 0; i < n; i++)
scanf("%lld", &x[i]);
sort(x, x + n);
ll l = -1e12, r = 1e12;
ll ans = linf;
int po=100;
while(po--)
{
ll mid = l + (r - l) / 3;
ll mmid = r - (r - l) / 3;
ll t1=f(mid);
ll t2=f(mmid);
if(t1 > t2)
{
l = mid;
}
else
{
r = mmid;
}
ans = std::min(ans, std::min(t1, t2));
}
printf("%lld\n", ans);
return 0;
}
/*
3 1
2 5 7
10 4
140 26 69 55 39 64 2 89 78 421
*/