凸包上删点我不会,那就将删点转成加点。
所以我们只要维护一个可以加点的动态凸包就好了。
每次加点先判断是否在凸包内,然后用set lowerbound找两边相邻的点,对两边分别进行维护。
#include <bits/stdc++.h>
#define pb push_back
#define memarray(array,val) memset(array,val,sizeof(array))
using namespace std;
const int mod=1e9+7;
const double PI=acos(-1.0);
const double EPS=1e-6;
inline int sgn(double a){
if(a<-EPS)return -1;
return a>EPS;
}
inline int cmp(double a,double b){
return sgn(a-b);
}
const int MAXN=2e5+10;
const int INF=0x3f3f3f3f;
int n,m,q;
int ty[MAXN],cancel[MAXN];
bool no[MAXN];
double ans;
struct Point{
double x,y;
Point(double _x=0.0,double _y=0.0){
x=_x;y=_y;
}
double len(){
return sqrt(len2());
}
double len2(){
return x*x+y*y;
}
void read(){
scanf("%lf%lf",&x,&y);
}
bool operator<(const Point p)const{
if(cmp(x,p.x)==0)return y<p.y;
return x<p.x;
}
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};
}
double operator*(const Point p)const{
return x*p.x+y*p.y;
}
double operator^(const Point p)const{
return x*p.y-y*p.x;
}
}p[MAXN],ptmp[MAXN];
Point p1,p2,p3;
set<Point>stk;
int Andrew(){
int num=0;
for(int i=1;i<=n;i++){
if(no[i])continue;
ptmp[++num]=p[i];
}
ptmp[++num]=p1;
ptmp[++num]=p2;
ptmp[++num]=p3;
sort(ptmp+1,ptmp+1+num);
stk.insert(ptmp[num]);
int len=1;
for(int i=num-1;i>=1;i--){
while(len>1){
set<Point>::iterator sss=stk.begin();
Point t1=*sss;
sss++;
Point t2=*sss;
if(sgn(((t1-t2)^(ptmp[i]-t2)))<0){
stk.erase(stk.begin());
len--;
}else{
break;
}
}
stk.insert(ptmp[i]);
len++;
}
return len;
}
void insert(int idx){
Point point=p[idx];
set<Point>::iterator it,it2;
it=lower_bound(stk.begin(),stk.end(),point);
it2=it;
it2--;
Point point1=*it2,point2=*it;
if(sgn(((point1-point2)^(point-point2)))>=0)return;
ans-=(point1-point2).len();
while(it2!=stk.begin()){
it2--;
point2=*it2;
if(sgn(((point2-point)^(point1-point)))>0){
stk.erase(point1);
ans-=(point1-point2).len();
point1=point2;
}else{
break;
}
}
Point leftPoint=point1;
it2=it;
point1=*it2;
it2++;
while(it2!=stk.end()){
point2=*it2;
if(sgn(((point1-point)^(point2-point)))>0){
stk.erase(point1);
ans-=(point1-point2).len();
point1=point2;
it2++;
}else{
break;
}
}
if(sgn(((point-point1)^(leftPoint-point1)))>=0){
stk.insert(point);
ans+=(point-leftPoint).len();
ans+=(point-point1).len();
}
}
void solve() {
Andrew();
Point pre={0,0};
for(auto i:stk){
ans+=(i-pre).len();
pre=i;
}
stack<double>two;
for(int i=q;i>=1;i--){
if(ty[i]==2){
two.push(ans);
}else{
insert(cancel[i]);
}
}
while(!two.empty()){
double tmp=two.top();
two.pop();
printf("%.2f\n",tmp);
}
}
void init(){
double x,y;
scanf("%lf",&x);
p1=(Point){0,0};
p2=(Point){x,0};
scanf("%lf%lf",&x,&y);
p3=(Point){x,y};
scanf("%d",&n);
for(int i=1;i<=n;i++)
p[i].read();
scanf("%d",&q);
for(int i=1;i<=q;i++){
scanf("%d",ty+i);
if(ty[i]==1){
scanf("%d",cancel+i);
no[cancel[i]]=true;
}
}
}
int main()
{
int T=1;
// scanf("%d",&T);
while(T--)
{
init();
solve();
}
return 0;
}