很简单的东西,维护凸包的上凸性而已,无聊来练练手,准备些NOI 2007 cash
#include <cstdio>
#include <cmath>
#include <set>
using namespace std;
const int MAXN = 300001;
const int MAXQ = 300001;
struct Point
{
bool flag;
double x,y;
bool operator < (const Point &rhs) const
{
return x < rhs.x || (x == rhs.x && y < rhs.y);
}
Point (){}
Point (double _x,double _y):x(_x),y(_y){flag = false;}
};
Point operator - (Point A,Point B)
{
return (Point){A.x-B.x,A.y-B.y};
}
double Cross(Point A,Point B)
{
return A.x*B.y-A.y*B.x;
}
Point P[MAXN];
set <Point> S;
set <Point> :: iterator it1,it2;
struct Q
{
int oper,id;
};
Q Ques[MAXQ];
int n,q;
double m,x,y;
double ans;
double Ans[MAXQ];
inline double dist(double x1,double y1,double x2,double y2)
{
return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
bool judge(Point p)
{
it1 = it2 = S.lower_bound(p);
it1--;
if (Cross(*it2-*it1,p-*it1) < 0) return true;
return false;
}
void insert(Point p)
{
if (judge(p)) return;
it1 = it2 = S.lower_bound(p);
it1--;
ans -= dist(it1->x,it1->y,it2->x,it2->y);
it1 = it2 = --S.lower_bound(p);
it2--;
while (true)//it1 != S.begin())
{
if (Cross(p-*it2,*it1-*it2) < 0)
{
ans -= dist(it1->x,it1->y,it2->x,it2->y);
S.erase(it1);
}
else break;
it1 = it2;
if (it2 != S.begin()) it2--;
}
it1 = it2 = S.lower_bound(p);
it2++;
while (true)//it2 != S.end())
{
if (Cross(p-*it2,*it1-*it2) > 0)
{
ans -= dist(it1->x,it1->y,it2->x,it2->y);
S.erase(it1);
}
else break;
it1 = it2;
it2++;
}
S.insert(p);
it1 = it2 = S.find(p);
it1++, it2--;
ans += dist(p.x,p.y,it1->x,it1->y)+dist(p.x,p.y,it2->x,it2->y);
}
int main()
{
scanf("%lf%lf%lf",&m,&x,&y);
S.insert((Point){0,0});
S.insert((Point){m,0});
S.insert((Point){x,y});
ans = dist(0,0,x,y)+dist(x,y,m,0);
scanf("%d",&n);
for (int i=1;i<=n;i++) scanf("%lf%lf",&P[i].x,&P[i].y);
scanf("%d",&q);
for (int i=1;i<=q;i++)
{
scanf("%d",&Ques[i].oper);
if (Ques[i].oper == 1) scanf("%d",&Ques[i].id), P[Ques[i].id].flag = true;
}
for (int i=1;i<=n;i++) if (!P[i].flag) insert(P[i]);
for (int i=q;i>=1;i--)
{
if (Ques[i].oper == 1) insert(P[Ques[i].id]);
else Ans[i] = ans;
}
for (int i=1;i<=q;i++) if (Ques[i].oper == 2) printf("%.2lf\n",Ans[i]);
return 0;
}
本文介绍了一个简单的算法练习,旨在通过维护凸包的上凸性来提升编程技巧,适合准备参加NOI2007比赛的选手。
492

被折叠的 条评论
为什么被折叠?



