题目描述
平面图&对偶图
平面图的定义:可以放在笛卡尔坐标系中,边只会在给定顶点处相交
把平面图中的每个区域+无穷域当作一个点,每条边变成两边的区域的连边,即为对偶图
把一条边拆成两条,每次找一个点,对于一条边找逆时针的下一条边(总方向是顺时针),直到找出一个环
因此要找一个块的内侧就可以按照上面的顺序寻找,找到的边所对应的块即为内侧
从u--v中u在v中的编号可以排序+二分,每条边只会经过一次
对于最小割可以把源汇连起来作为一个新的区域,从该块到无穷域的最短路即为最小割
题解
总面积很好求,问题是怎么求面积的平方和
把对偶图建一棵生成树,以无穷域为根统计子树和
无穷域找法:可以先判掉最外圈,具体为找y最大的点,然后逆时针寻找
也可以直接找面积为负的区域
如果一个询问经过的边不在生成树上就不管,如果内侧块(即当前边所对应的块,在顺时针方向)在生成树上为儿子就加上答案,否则减去答案
画一下就可以发现这样是对的
注意题目给出询问点是逆时针,所以要反过来
code
很好写(3.7k)
#include
#include
#include
#include
#include
#include
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
//#define file
using namespace std;
struct p{
int x,y;
} a[200001];
struct type{
int x,y;
double s;
} b[1200001];
struct Type{
int x,id;
} B[1200001];
int aa[800001][2];
int ls[400002];
bool bz[1200001];
int c[1200001];
int C[1200001];
int st[200002];
long long S[400002];
long long S2[400002];
int fa[400002];
int FA[400002];
int q[200002];
int n,m,Q,i,j,k,l,K,L,tot,N,Tot,mx,mx2,len,x,X,y;
long long lsans,ans1,ans2,Gcd;
char ch;
void New(int x,int y)
{
++len;
aa[len][0]=y;
aa[len][1]=ls[x];
ls[x]=len;
}
int getint()
{
int x=0,k=1;
ch=getchar();
while (ch<'0' || ch>'9') k=(ch=='-')?-1:k,ch=getchar();
while (ch>='0' && ch<='9') x=x*10+(ch-'0'),ch=getchar();
return x*k;
}
long long cj(p a,p b)
{
return b.x*a.y-a.x*b.y;
}
bool cmp(type a,type b) {return a.x0)
return 0;
return M_PI;
}
if (!x)
{
if (y>0)
return M_PI/2;
return M_PI*3/2;
}
if (x>0 && y>0) return atan(1.0*y/x);
if (x>0 && y<0) return atan(1.0*y/x)+M_PI*2;
return atan(1.0*y/x)+M_PI;
}
long long gcd(long long a,long long b)
{
long long r=a%b;
while (r)
a=b,b=r,r=a%b;
return b;
}
int find(int t,int x)
{
int l=st[t],r=st[t+1]-1,mid;
while (lmx)
mx=a[i].y,mx2=i;
N=1;
fo(j,st[mx2],st[mx2+1]-1)
if (b[j].s>=M_PI-0.00000001)
{
work(mx2,j);
break;
}
// ---对偶图
fo(i,1,n)
{
fo(j,st[i],st[i+1]-1)
if (!bz[j])
{
++N;
work(i,j);
}
}
fo(i,1,N) fa[i]=i;
// ---生成树
fo(i,1,n)
{
fo(j,st[i],st[i+1]-1)
{
k=find(b[j].y,i);
C[j]=c[k];
if (gf(c[j])!=gf(c[k]))
{
fa[fa[c[j]]]=fa[c[k]];
bz[j]=bz[k]=0;
New(c[j],c[k]);
New(c[k],c[j]);
}
}
}
dfs(0,1);
// ---
for (;Q;--Q)
{
lsans=ans1,ans1=ans2=0;
Tot=getint();Tot=(Tot+lsans%n)%n+1;
fo(i,1,Tot) q[i]=getint(),q[i]=(q[i]+lsans%n)%n+1;
fd(i,Tot,1)
{
j=find(q[i%Tot+1],q[i]);
if (!bz[j])
{
if (FA[c[j]]==C[j])
ans1+=S2[c[j]];
else
if (FA[C[j]]==c[j])
ans1-=S2[C[j]];
}
ans2+=cj(a[q[i%Tot+1]],a[q[i]]);
}
ans2*=2;
Gcd=gcd(ans1,ans2);
ans1/=Gcd,ans2/=Gcd;
printf("%lld %lld\n",ans1,ans2);
}
}