codeforces1195F

題目描述

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

題目大意

定義兩個凸多邊形的“合併”:將凸多邊形內的每個點相加(向量加)組成一個新凸多邊形
若干次詢問,求[L,R]內凸多邊形相加後得到的凸多邊形的頂點數

前言

因爲C題讀錯題導致E題沒調出來,rank2000+
F題比賽時沒看,後來發現不難

正解

一個並不顯然的結論:
兩個凸多邊形相加得到的頂點數爲這兩個多邊形同逆時針方向上不同的方向種類
感性證明一下
凸多邊形相加等於將一個凸多邊形按另一個的邊界移動
如果另一個的一條向量的方向在第一個中沒有出現,那麼移動後就一定會多出一條


然後就很偷稅愉悅地離散化+莫隊亂搞

code

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define PI 3.14159265358979323846
using namespace std;

struct type{
	double s;
	int id;
} a[300001];
int b[300001];
int ls[100001];
double x[300001];
double y[300001];
struct Type{
	int l,r,s,id;
} q[100001];
int ans[100001];
int c[300001];
int N,Q,n,i,j,k,tot,Ans,S,l,r;

bool cmp(type a,type b)
{
	return a.s<b.s;
}

bool Cmp(Type a,Type b)
{
	return a.s<b.s || a.s==b.s && a.r<b.r;
}

int gcd(int n,int m)
{
	int r=n%m;
	
	while (!r)
	{
		n=m;
		m=r;
		r=n%m;
	}
	
	return m;
}

double xl(int i,int j)
{
	if (x[i]==x[j])
	return (y[i]<y[j])?PI/2:PI*1.5;
	else
	if (y[i]==y[j])
	return (x[i]<x[j])?0:PI;
	else
	if (y[i]<y[j])
	{
		if (x[i]<x[j])
		return atan((y[j]-y[i])/(x[j]-x[i]));
		else
		return atan((y[j]-y[i])/(x[j]-x[i]))+PI;
	}
	else
	{
		if (x[j]<x[i])
		return atan((y[j]-y[i])/(x[j]-x[i]))+PI;
		else
		return atan((y[j]-y[i])/(x[j]-x[i]))+PI+PI;
	}
}

int main()
{
//	freopen("f.in","r",stdin);
	
	scanf("%d",&N);
	fo(l,1,N)
	{
		ls[l]=tot+1;
		
		scanf("%d",&n);
		fo(i,1,n)
		scanf("%lf%lf",&x[i],&y[i]);
		
		fo(i,1,n-1)
		{
			++tot;
			a[tot].s=xl(i,i+1);
			a[tot].id=tot;
		}
		++tot;
		a[tot].s=xl(n,1);
		a[tot].id=tot;
	}
	ls[N+1]=tot+1;
	S=floor(sqrt(tot));
	
	sort(a+1,a+tot+1,cmp);
	
	j=0;
	fo(i,1,tot)
	{
		if (i==1 || a[i].s-a[i-1].s>0.00000000001)
		++j;
		b[a[i].id]=j;
	}
	
	scanf("%d",&Q);
	fo(i,1,Q)
	{
		scanf("%d%d",&q[i].l,&q[i].r);
		q[i].l=ls[q[i].l];
		q[i].r=ls[q[i].r+1]-1;
		q[i].id=i;
		q[i].s=q[i].l/S;
	}
	
	sort(q+1,q+Q+1,Cmp);
	
	l=0;
	r=0;
	Ans=0;
	fo(i,1,Q)
	{
		while (q[i].l<l)
		{
			--l;
			++c[b[l]];
			if (c[b[l]]==1)
			++Ans;
		}
		while (r<q[i].r)
		{
			++r;
			++c[b[r]];
			if (c[b[r]]==1)
			++Ans;
		}
		
		while (l<q[i].l)
		{
			--c[b[l]];
			if (!c[b[l]])
			--Ans;
			++l;
		}
		while (q[i].r<r)
		{
			--c[b[r]];
			if (!c[b[r]])
			--Ans;
			--r;
		}
		
		ans[q[i].id]=Ans;
	}
	
	fo(i,1,Q)
	printf("%d\n",ans[i]);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章