卧薪尝胆,厚积薄发。
      
    
            HAOI2011 防线修建
        
        
        Description:
支持一个数据结构,删除一个点,询问上凸壳的长度。
$1\leqslant n\leqslant 10^5$
Solution:
删除凸包上的点是一个经典的难解问题,所以时光倒流转化为插入,可以用一个
$splay$
动态维护凸壳并实时维护当前凸壳长度,注意答案的更新有很多细节。
Code:
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cctype>
#include<cstring>
using namespace std;
inline int rd()
{
	register int res = 0,f = 1;
	register char c = getchar();
	while(!isdigit(c))
	{
		if(c == '-')f = -1;
		c = getchar();
	}
	while(isdigit(c))
	{
		res = (res << 1) + (res << 3) + c - '0';
		c = getchar();
	}
	return res * f;
}
int n,x,y,m;
#define MAXN 100010
struct point
{
	int x,y;
}p[MAXN];
#define MAXQ 200010
int cnt[MAXN];
struct query
{
	int k,type;
	double res;
}q[MAXQ];
int qn;
double ans = 0;
double dis(point a,point b)
{
	return sqrt(double(a.x - b.x) * double(a.x - b.x) + double(a.y - b.y) * double(a.y - b.y));
}
struct node
{
	int fa,c[2];
	point p;
}t[MAXN];
int root;
int ptr = 0;
int newnode(){return ++ptr;}
int id(int k){return (t[t[k].fa].c[0] == k ? 0 : 1);}
void connect(int k,int f,int p){t[k].fa = f;t[f].c[p] = k;return;}
void rotate(int x)
{
	int y = t[x].fa,z = t[y].fa,fx = id(x),fy = id(y);
	connect(t[x].c[fx ^ 1],y,fx);
	connect(y,x,fx ^ 1);connect(x,z,fy);
	return;
}
void splay(int x)
{
	while(t[x].fa != 0)
	{
		int y = t[x].fa;
		if(t[y].fa == 0){rotate(x);break;}
		if(id(x) == id(y)){rotate(y);rotate(x);}
		else{rotate(x);rotate(x);}
	}
	root = x;
	return;
}
int pre()
{
	int cur = t[root].c[0];
	if(cur == 0)return 0;
	while(t[cur].c[1] != 0)cur = t[cur].c[1];
	return cur;
}
int nxt()
{
	int cur = t[root].c[1];
	if(cur == 0)return 0;
	while(t[cur].c[0] != 0)cur = t[cur].c[0];
	return cur;
}
double slope(point a,point b){return double(a.y - b.y) / double(a.x - b.x);}
void remove(int k)
{
	splay(k);
	int nrt = nxt();
	splay(nrt);
	connect(t[k].c[0],nrt,0);
	return;
}
void maintain(int k)
{
	splay(k);
	int pr = pre(),nx = nxt();
	if(slope(t[k].p,t[pr].p) <= slope(t[k].p,t[nx].p))
	{
		ans -= dis(t[k].p,t[pr].p) + dis(t[k].p,t[nx].p);
		ans += dis(t[pr].p,t[nx].p);
		remove(k);
		return;
	}
	while(true)
	{
		splay(k);int p = pre();
		splay(p);int pp = pre();
		if(pp == 0)break;
		if(slope(t[pp].p,t[p].p) <= slope(t[p].p,t[k].p))
		{
			ans -= dis(t[pp].p,t[p].p) + dis(t[p].p,t[k].p);
			ans += dis(t[k].p,t[pp].p);
			remove(p);
		}
		else break;
	}
	while(true)
	{
		splay(k);int p = nxt();
		splay(p);int pp = nxt();
		if(pp == 0)break;
		if(slope(t[pp].p,t[p].p) >= slope(t[p].p,t[k].p))
		{
			ans -= dis(t[pp].p,t[p].p) + dis(t[p].p,t[k].p);
			ans += dis(t[k].p,t[pp].p);
			remove(p);
		}
		else break;
	}
	return;
}
void insert(point k)
{
	int cur = root;
	int pos = newnode();
	t[pos].p = k;
	while(true)
	{
		if(k.x < t[cur].p.x)
		{
			if(t[cur].c[0] != 0)cur = t[cur].c[0];
			else
			{
				splay(cur);
				int pr = pre();
				splay(pr);splay(cur);
				ans -= dis(t[t[cur].c[0]].p,t[cur].p);
				ans += dis(t[t[cur].c[0]].p,t[pos].p) + dis(t[pos].p,t[cur].p);
				connect(t[cur].c[0],pos,0);connect(pos,cur,0);
				maintain(pos);
				return;
			}
		}
		else if(k.x > t[cur].p.x)
		{
			if(t[cur].c[1] != 0)cur = t[cur].c[1];
			else
			{
				splay(cur);
				int nx = nxt();
				splay(nx);splay(cur);
				ans -= dis(t[t[cur].c[1]].p,t[cur].p);
				ans += dis(t[t[cur].c[1]].p,t[pos].p) + dis(t[pos].p,t[cur].p);
				connect(t[cur].c[1],pos,1);connect(pos,cur,1);
				maintain(pos);
				return;
			}
		}
		else
		{
			splay(cur);
			if(k.y <= t[cur].p.y)return;
			ans -= dis(t[pre()].p,t[cur].p) + dis(t[nxt()].p,t[cur].p);
			t[cur].p = k;
			ans += dis(t[pre()].p,t[cur].p) + dis(t[nxt()].p,t[cur].p);
			maintain(cur);
		}
	}
	return;
}
int main()
{
	scanf("%d%d%d",&n,&x,&y);
	scanf("%d",&m);
	for(int i = 1;i <= m;++i)
	{
		p[i].x = rd();p[i].y = rd();
	}
	scanf("%d",&qn);
	for(int i = 1;i <= qn;++i)
	{
		q[i].type = rd();
		if(q[i].type == 1)
		{
			q[i].k = rd();
			++cnt[q[i].k];
		}
	}
	ans = dis((point){0,0},(point){x,y}) + dis((point){x,y},(point){n,0});
	root = newnode();
	t[root].p.x = x;t[root].p.y = y;
	int lef = newnode(),rig = newnode();
	t[lef].p = (point){0,0};t[rig].p = (point){n,0};
	connect(lef,root,0);connect(rig,root,1);
	for(int i = 1;i <= m;++i)
	{
		if(cnt[i] == 0)
		{
			insert(p[i]);
		}
	}
	for(int i = qn;i >= 1;--i)
	{
		if(q[i].type == 1)
		{
			--cnt[q[i].k];
			if(cnt[q[i].k] == 0)insert(p[q[i].k]);
		}
		else
		{
			q[i].res = ans;
		}
	}
	for(int i = 1;i <= qn;++i)
		if(q[i].type == 2)
			printf("%.2lf\n",q[i].res);
	return 0;
}
        Copyright © 2020
        
          wjh15101051
        
      
      ღゝ◡╹)ノ♡
     Date: Sat Nov 03 15:08:06 CST 2018
          Date: Sat Nov 03 15:08:06 CST 2018
           In Category:
          In Category:
           In tag:
          In tag:
 
         Timeline
            Timeline
           About
            About
           Toolbox
            Toolbox
           Friends
              Friends