2022年3月6日更新
题目
求凸包后,计算凸包周长,答案再加上2*pi*r
板子一
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+20;
const double pi=acos(-1.0),eps=1e-8;
struct Point{
double x,y;
Point(){}
Point(double xx,double yy){
x = xx;
y = yy;
}
Point operator-(const Point a)const{
return Point(x-a.x,y-a.y);
}
}p[N],ch[N];
bool cmp(Point a,Point b){
if(a.x == b.x) return a.y < b.y;
return a.x < b.x;
}
double det (Point a, Point b){
return a.x * b.y - a.y * b.x;
}
double sq(double x){
return x*x;
}
double cal(Point a,Point b){
return sqrt(sq(a.x-b.x)+sq(a.y-b.y));
}
int ConvexHull(Point *p,int n,Point *ch){
sort(p,p+n,cmp);
int m=0;
for(int i=0;i<n;i++){
while(m>1&&det(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=eps)m--;
ch[m++]=p[i];
}
int k=m;
for(int i=n-2;i>=0;i--){
while(m>k&&det(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=eps)m--;
ch[m++]=p[i];
}
if(n>1)m--;
return m;
}
int n,k,c;
double r,ans;
int main(){
scanf("%d%lf",&n,&r);
for(int i=0;i<n;++i){
scanf("%d",&k);
while(k--){
scanf("%lf%lf",&p[c].x,&p[c].y);
c++;
}
}
int x=ConvexHull(p,c,ch);
ans=cal(ch[0],ch[x-1])+2.0*pi*r;
for(int i=1;i<x;++i){
ans+=cal(ch[i],ch[i-1]);
}
printf("%.5lf\n",ans);
return 0;
}
板子二
函数更全面一些
#include <bits/stdc++.h>
#define REP(i,n) for(int i=0;i<n;++i)
using namespace std;
const double EPS = 1e-8;
inline int sign(double a){
return a < -EPS ? -1 : a > EPS;
}
struct Point{
double x, y;
Point(){}
Point(double _x, double _y):x(_x), y(_y){}
Point operator+(const Point&p)const{
return Point(x+p.x, y+p.y);
}
Point operator-(const Point&p)const{
return Point(x-p.x, y-p.y);
}
Point operator*(double d)const{
return Point(x*d, y*d);
}
Point operator/(double d)const{
return Point(x/d, y/d);
}
bool operator<(const Point&p)const{
int c=sign(x-p.x);
if(c)return c==-1;
return sign(y-p.y)==-1;
}
double dot(const Point&p)const{
return x*p.x+y*p.y;
}
double det(const Point&p)const{
return x*p.y-y*p.x;
}
double alpha()const{
return atan2(y,x);
}
double distTo(const Point&p)const{
double dx=x-p.x,dy=y-p.y;
return hypot(dx,dy);
}
double alphaTo(const Point&p)const{
double dx=x-p.x,dy=y-p.y;
return atan2(dy,dx);
}
void read(){
scanf("%lf%lf",&x,&y);
}
double abs(){
return hypot(x,y);
}
double abs2(){
return x*x+y*y;
}
void write(){
cout<<"("<<x<<","<<y<<")"<<endl;
}
};
#define cross(p1,p2,p3) ((p2.x-p1.x)*(p3.y-p1.y)-(p3.x-p1.x)*(p2.y-p1.y))
#define crossOp(p1,p2,p3) sign(cross(p1,p2,p3))
Point isSS(Point p1, Point p2, Point q1, Point q2){
double a1=cross(q1,q2,p1),a2=-cross(q1,q2,p2);
Point temp;
temp.x=sign((p1.x*a2+p2.x*a1)/(a1+a2))==0?0:(p1.x*a2+p2.x*a1)/(a1+a2);
temp.y=sign((p1.y*a2+p2.y*a1)/(a1+a2))==0?0:(p1.y*a2+p2.y*a1)/(a1+a2);
return temp;
}
vector<Point> convexHull(vector<Point> ps){
int n=ps.size();
if(n<=1)return ps;
sort(ps.begin(), ps.end());
vector<Point> qs;
for(int i=0;i<n;qs.push_back(ps[i++])){
while(qs.size()>1 && crossOp(qs[qs.size()-2],qs.back(),ps[i])<=0){
qs.pop_back();
}
}
for(int i=n-2,t=qs.size();i>=0;qs.push_back(ps[i--])){
while(qs.size()>t && crossOp(qs[qs.size()-2],qs.back(),ps[i])<=0){
qs.pop_back();
}
}
qs.pop_back();
return qs;
}
int main(){
int n;
double r;
cin>>n>>r;
vector<Point>ps;
vector<Point>qs;
Point temp;
for(int i=1;i<=n;i++){
int k;
cin>>k;
while(k--){
temp.read();
ps.push_back(temp);
}
}
qs=convexHull(ps);
int l=qs.size();
double sum=0;
for(int i=0;i<l;i++){
sum+=qs[i].distTo(qs[(i+1)%l]);
}
sum+=2.0*acos(-1.0)*r;
cout<<fixed<<setprecision(5)<<sum<<endl;
return 0;
}
2023年2月12日更新
题目:ABC289 G - Shopping in AtCoder store
构建建最优直线的凸包,即能取到最大值的若干条直线,然后求横坐标x对应的y=kx+b最大值,
在凸包上二分或者离线增序遍历均可
#include <bits/stdc++.h>
using i64 = long long;
using T = long long;
struct Point {
T x;
T y;
Point(T x = 0, T y = 0) : x(x), y(y) {}
Point &operator+=(const Point &p) {
x += p.x, y += p.y;
return *this;
}
Point &operator-=(const Point &p) {
x -= p.x, y -= p.y;
return *this;
}
Point &operator*=(const T &v) {
x *= v, y *= v;
return *this;
}
friend Point operator-(const Point &p) {
return Point(-p.x, -p.y);
}
friend Point operator+(Point lhs, const Point &rhs) {
return lhs += rhs;
}
friend Point operator-(Point lhs, const Point &rhs) {
return lhs -= rhs;
}
friend Point operator*(Point lhs, const T &rhs) {
return lhs *= rhs;
}
};
T dot(const Point &a, const Point &b) {
return a.x * b.x + a.y * b.y;
}
T cross(const Point &a, const Point &b) {
return a.x * b.y - a.y * b.x;
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int n, m;
std::cin >> n >> m;
std::z b(n);
for (int i = 0; i < n; i++) {
std::cin >> b[i];
}
std::sort(b.begin(), b.end(), std::greater());
std::vector<Point> h;
for (int i = 0; i < n; i++) {
Point p(i + 1, 1LL * (i + 1) * b[i]); // (x,y)==(k,b)
while (h.size() > 1 && cross(h.back() - h.end()[-2], p - h.back()) >= 0) {
h.pop_back();
}
h.push_back(p);
}
for (int i = 0; i < m; i++) {
int c;
std::cin >> c;
Point p(c, 1);
int lo = 0, hi = h.size() - 1;
while (lo < hi) {
int m = (lo + hi) / 2;
if (dot(h[m], p) < dot(h[m + 1], p)) {
lo = m + 1;
} else {
hi = m;
}
}
i64 ans = dot(h[lo], p);
std::cout << ans << " \n"[i == m - 1];
}
return 0;
}