题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2300
题意:给出一些点,两种操作:(1)删掉某个点;(2)求剩下点构成的凸包的周长。(保证凸包有一条边为x轴,即保证凸包上有两点在x轴上,这条边不算在周长中)
思路:离线。先将所有删掉的点删掉,其余点找到一个中心点(由题意其余点至少三个所以中心点存在),求每个点关于中心角的转角,以转角为关键字建立set。对于询问倒着操作,每次插入时找到两边的点将之间的删掉。如下图所示。
#include <iostream>
#include <cstdio>
#include <string.h>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <map>
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
#define abs(x) ((x)>=0?(x):-(x))
#define i64 long long
#define u32 unsigned int
#define u64 unsigned long long
#define clr(x,y) memset(x,y,sizeof(x))
#define CLR(x) x.clear()
#define ph(x) push(x)
#define pb(x) push_back(x)
#define Len(x) x.length()
#define SZ(x) x.size()
#define PI acos(-1.0)
#define sqr(x) ((x)*(x))
#define MP(x,y) make_pair(x,y)
#define EPS 1e-10
#define FOR0(i,x) for(i=0;i<x;i++)
#define FOR1(i,x) for(i=1;i<=x;i++)
#define FOR(i,a,b) for(i=a;i<=b;i++)
#define FORL0(i,a) for(i=a;i>=0;i--)
#define FORL1(i,a) for(i=a;i>=1;i--)
#define FORL(i,a,b)for(i=a;i>=b;i--)
#define rush() int CC;for(scanf("%d",&CC);CC--;)
#define Rush(n) while(scanf("%d",&n)!=-1)
using namespace std;
void RD(int &x){scanf("%d",&x);}
void RD(i64 &x){scanf("%lld",&x);}
void RD(u64 &x){scanf("%I64u",&x);}
void RD(u32 &x){scanf("%u",&x);}
void RD(double &x){scanf("%lf",&x);}
void RD(int &x,int &y){scanf("%d%d",&x,&y);}
void RD(i64 &x,i64 &y){scanf("%lld%lld",&x,&y);}
void RD(u32 &x,u32 &y){scanf("%u%u",&x,&y);}
void RD(double &x,double &y){scanf("%lf%lf",&x,&y);}
void RD(int &x,int &y,int &z){scanf("%d%d%d",&x,&y,&z);}
void RD(i64 &x,i64 &y,i64 &z){scanf("%lld%lld%lld",&x,&y,&z);}
void RD(u32 &x,u32 &y,u32 &z){scanf("%u%u%u",&x,&y,&z);}
void RD(double &x,double &y,double &z){scanf("%lf%lf%lf",&x,&y,&z);}
void RD(char &x){x=getchar();}
void RD(char *s){scanf("%s",s);}
void RD(string &s){cin>>s;}
void PR(int x) {printf("%d\n",x);}
void PR(int x,int y) {printf("%d %d\n",x,y);}
void PR(i64 x) {printf("%lld\n",x);}
void PR(u32 x) {printf("%u\n",x);}
void PR(u64 x) {printf("%llu\n",x);}
void PR(double x) {printf("%.2lf\n",x);}
void PR(char x) {printf("%c\n",x);}
void PR(char *x) {printf("%s\n",x);}
void PR(string x) {cout<<x<<endl;}
void upMin(int &x,int y) {if(x>y) x=y;}
void upMin(i64 &x,i64 y) {if(x>y) x=y;}
void upMin(double &x,double y) {if(x>y) x=y;}
void upMax(int &x,int y) {if(x<y) x=y;}
void upMax(i64 &x,i64 y) {if(x<y) x=y;}
void upMax(double &x,double y) {if(x<y) x=y;}
const int mod=1000000000;
const i64 inf=((i64)1)<<60;
const double dinf=1000000000000000000.0;
const int INF=1000000005;
const int N=200005;
int DB(double x)
{
if(x>1e-10) return 1;
if(x<-1e-10) return -1;
return 0;
}
struct node
{
int x,y;
double ang;
node(){}
node(int _x,int _y)
{
x=_x;
y=_y;
}
int operator<(const node &a) const
{
return DB(ang-a.ang)<0;
}
int operator==(const node &a) const
{
return x==a.x&&y==a.y;
}
node operator-(node a)
{
return node(x-a.x,y-a.y);
}
int operator*(node a)
{
return x*a.y-y*a.x;
}
};
int under(node a,node b,node s)
{
a.x-=s.x; a.y-=s.y;
b.x-=s.x; b.y-=s.y;
return b.x*a.y-b.y*a.x<0;
}
double dis(node a,node b)
{
a.x-=b.x;
a.y-=b.y;
return sqrt(1.0*a.x*a.x+1.0*a.y*a.y);
}
set<node> p;
double s;
#define type set<node>::iterator
type last(type it)
{
if(it==p.begin()) it=p.end();
return --it;
}
type next(type it)
{
if(++it==p.end()) it=p.begin();
return it;
}
int cross(node a,node b,node p)
{
return (b-a)*(p-a);
}
double X,Y;
double getAng(node a)
{
return atan2(a.y-Y,a.x-X);
}
void add(node a)
{
type it=last(p.lower_bound(a));
node b=*it,x,y;
if(cross(b,*next(it),a)>0) return;
type L=it,R=it;
while(cross(a,*next(R),*R)>=0) R=next(R);
while(cross(a,*L,*last(L))>=0) L=last(L);
for(it=L;it!=R;it=next(it))
{
x=*it;
y=*next(it);
s-=dis(x,y);
}
for(it=next(L);it!=R;)
{
it=next(it);
p.erase(last(it));
}
x=*L;y=*R;
s+=dis(x,a)+dis(a,y);
p.insert(a);
}
vector<node> V;
int q[N];
int n,x,y,m;
int op[N],a[N],Q;
int main()
{
RD(n,x,y);
V.pb(node(0,0));
V.pb(node(n,0));
V.pb(node(x,y));
X=(n+x)/3.0;
Y=y/3.0;
V[0].ang=getAng(V[0]);
V[1].ang=getAng(V[1]);
V[2].ang=getAng(V[2]);
RD(m);
int i,k=3;
FOR1(i,m) RD(x,y),V.pb(node(x,y)),V[k].ang=getAng(V[k]),k++;
p.insert(V[0]);
p.insert(V[1]);
p.insert(V[2]);
s=dis(V[0],V[2])+dis(V[1],V[2]);
RD(Q);
FOR1(i,Q)
{
RD(op[i]);
if(op[i]==1) RD(a[i]),q[a[i]+2]=1;
}
m+=3;
for(i=3;i<m;i++) if(!q[i]) add(V[i]);
vector<double> A;
for(i=Q;i>=1;i--)
{
if(op[i]==1) add(V[a[i]+2]);
else A.pb(s);
}
for(i=SZ(A)-1;i>=0;i--) PR(A[i]);
}