考虑先将平面图转化为对偶图。具体地,将无向边拆成两条有向边。每次考虑找到包围一个区域的所有边。对当前考虑的边,找到该边的反向边在该边终点的出边集中,按极角序排序的后继,这条后继边也是包围该区域的边。这样对偶图就建好了。

  考虑怎么用对偶图解决原问题。将外围的无限域也作为对偶图中的一个点,以其为根随便找一棵生成树,计算子树内面积和及面积平方和。对于询问,考虑多边形上每条边,其同时也是对偶图中两点的边。如果该边在生成树中是非树边,扔掉不管;如果是树边,若由父亲指向儿子,则加上儿子权值,否则减掉儿子权值。具体只能感性理解。

  注意对偶图中两点间可能有重边,判断是否为非树边时小心一点。因为这个调一年也是没谁了。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<map>
#include<vector>
#include<cassert>
using namespace std;
#define ll long long
#define Vector point
#define N 400010
#define M 1200010
ll gcd(ll n,ll m){return m==?n:gcd(m,n%m);}
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
int n,m,q,b[N],sur[M],nxt[M],t=-;
map<int,int> id[N],tag;
ll lastx,lasty;
struct point
{
int x,y;
Vector operator +(const Vector&a) const
{
return (Vector){x+a.x,y+a.y};
}
Vector operator -(const Vector&a) const
{
return (Vector){x-a.x,y-a.y};
}
ll operator *(const Vector&a) const
{
return 1ll*x*a.y-1ll*y*a.x;
}
bool operator <(const Vector&a) const
{
return atan2(x,y)<atan2(a.x,a.y);
}
}a[N];
struct edge{int x,y;}e[M];
struct data
{
Vector p;int id;
bool operator <(const data&a) const
{
return p<a.p;
}
};
vector<data> c[N];
namespace newgraph
{
int n,p[N],fa[N],t=,root;
ll sum[N],sqr[N],area[N];
struct data{int to,nxt,id;}edge[M];
void addedge(int x,int y,int z){t++;edge[t].to=y,edge[t].nxt=p[x],edge[t].id=z,p[x]=t;}
void dfs(int k)
{
sum[k]=area[k]<<,sqr[k]=area[k]*area[k];
for (int i=p[k];i;i=edge[i].nxt)
if (!fa[edge[i].to]&&edge[i].to!=root)
{
tag[edge[i].id]=-,tag[edge[i].id^]=;
fa[edge[i].to]=k;
dfs(edge[i].to);
sum[k]+=sum[edge[i].to],sqr[k]+=sqr[edge[i].to];
}
}
}
void addedge(int x,int y)
{
t++,e[t].x=x,e[t].y=y;id[x][y]=t;
c[x].push_back((data){a[y]-a[x],t});
}
void build()
{
for (int i=;i<=n;i++)
if (c[i].size())
{
sort(c[i].begin(),c[i].end());
for (int j=;j<c[i].size()-;j++)
nxt[c[i][j].id]=c[i][j+].id;
nxt[c[i][c[i].size()-].id]=c[i][].id;
}
for (int i=;i<(m<<);i++)
if (!sur[i])
{
++newgraph::n;
int x=i;ll y=;
do
{
sur[x]=newgraph::n;
y+=a[e[x].x]*a[e[x].y];
x=nxt[x^];
}while (!sur[x]);
if (y<) newgraph::root=newgraph::n;
newgraph::area[newgraph::n]=y;
}
for (int i=;i<(m<<);i++)
newgraph::addedge(sur[i],sur[i^],i);
newgraph::dfs(newgraph::root);
}
signed main()
{
#ifndef ONLINE_JUDGE
freopen("bzoj4541.in","r",stdin);
freopen("bzoj4541.out","w",stdout);
const char LL[]="%I64d ";
#else
const char LL[]="%lld ";
#endif
n=read(),m=read(),q=read();
for (int i=;i<=n;i++) a[i].x=read(),a[i].y=read();
for (int i=;i<=m;i++)
{
int x=read(),y=read();
addedge(x,y),addedge(y,x);
}
build();
while (q--)
{
int t=(read()+lastx)%n+;
for (int i=;i<=t;i++) b[i]=(read()+lastx)%n+;
lastx=,lasty=;
for (int i=;i<=t;i++)
{
int x=tag[id[b[i]][b[i%t+]]];
if (x)
{
int y=x==?sur[id[b[i]][b[i%t+]]]:sur[id[b[i%t+]][b[i]]];
lasty+=x*newgraph::sum[y],lastx+=x*newgraph::sqr[y];
}
}
ll tmp=gcd(lastx,lasty);
lastx/=tmp,lasty/=tmp;
printf(LL,lastx),printf(LL,lasty),printf("\n");
}
return ;
}

BZOJ4541 HNOI2016矿区(平面图转对偶图)的更多相关文章

  1. [BZOJ4541][HNOI2016]矿区(平面图转对偶图)

    https://www.cnblogs.com/ljh2000-jump/p/6423399.html #include<cmath> #include<vector> #in ...

  2. BZOJ 4541: [Hnoi2016]矿区 平面图转对偶图+DFS树

    4541: [Hnoi2016]矿区 Time Limit: 30 Sec  Memory Limit: 512 MBSubmit: 433  Solved: 182[Submit][Status][ ...

  3. BZOJ4541 [Hnoi2016]矿区

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...

  4. [HNOI2016]矿区

    [HNOI2016]矿区 平面图转对偶图 方法: 1.分成正反两个单向边,每个边属于一个面 2.每个点按照极角序sort出边 3.枚举每一个边,这个边的nxt就是反边的前一个(这样找到的是面的边逆时针 ...

  5. LOJ#2052. 「HNOI2016」矿区(平面图转对偶图)

    题面 传送门 题解 总算会平面图转对偶图了-- 首先我们把无向边拆成两条单向边,这样的话每条边都属于一个面.然后把以每一个点为起点的边按极角排序,那么对于一条边\((u,v)\),我们在所有以\(v\ ...

  6. bzoj 4541: [Hnoi2016]矿区【平面图转对偶图+生成树】

    首先平面图转对偶图,大概思路是每条边存正反,每个点存出边按极角排序,然后找每条边在它到达点的出边中极角排序的下一个,这样一定是这条边所属最小多边形的临边,然后根据next边找出所有多边形,用三角剖分计 ...

  7. 【LG3249】[HNOI2016]矿区

    [LG3249][HNOI2016]矿区 题面 洛谷 题解 先平面图转对偶图, 建好了对偶图之后随意拿出一个生成树,以无边界的范围为根. 无边界的范围很好求,用叉积算出有向面积时,算出来是负数的就是无 ...

  8. 【BZOJ-2007】海拔 最小割 (平面图转对偶图 + 最短路)

    2007: [Noi2010]海拔 Time Limit: 20 Sec  Memory Limit: 552 MBSubmit: 2095  Solved: 1002[Submit][Status] ...

  9. 平面图转对偶图(Bzoj1001:狼抓兔子)

    如果只会用最小割做这道题那就太菜辣 引入 来自某学长 平面图:在平面上边不相交的图(边可以绕着画) 那么平面图的边与边就围成了许多个区域(这与你画图的方式有关) 定义对偶图:把相邻的两个区域连上边,形 ...

随机推荐

  1. not annotated with HTTP method type (ex. GET, POST) 问题解决

    大多数情况是真的而没有写method = RequestMethod.GET.POST等注解, 有时这么写了也报类似异常,如下 @FeignClient("microservice-prov ...

  2. Linux 防火墙 开放 端口 iptables

    查看状态:iptables -L -n 方法1.使用iptables开放如下端口/sbin/iptables -I INPUT -p tcp --dport 8000 -j ACCEPT保存/etc/ ...

  3. Linux DNS原理简介及配置

    Linux DNS原理简介及配置 DNS简介 DNS原理 域名解析的过程 资源记录 DNS BIND安装配置 一.简介 一般来讲域名比IP地址更加的有含义.也更容易记住,所以通常用户更习惯输入域名来访 ...

  4. Luogu3350 ZJOI2016 旅行者 最短路、分治

    传送门 题意:给出一个$N \times M$的网格图,边有边权,$Q$组询问,每组询问$(x_1,y_1)$到$(x_2,y_2)$的最短路.$N \times M \leq 2 \times 10 ...

  5. Lean Data Innovation Sharing Salon(2018.09.15)

    时间:2018.09.15地点:北京国华投资大厦

  6. 在Windows7上如何找到Cookie

    摘要 出于兴趣爱好,前一阵子做了一个网页,网页中需要用到Cookie,但是,根据书上的说明,并没有找打教材中所说的Cookie的位置,本文就主要介绍在计算机(Win7)中Cookie的存放位置,同样适 ...

  7. Ionic2 下处理 Android 设备下返回按钮的事件

    原文发表于我的技术博客 本文分享了 Ionic2 下处理 Android 设备下返回按钮的事件,供参考. 原文发表于我的技术博客 代码中我分享了如何捕捉 Ionic2 项目在 Android 设备下返 ...

  8. Python下操作Memcache/Redis/RabbitMQ说明

    一.MemcacheMemcache是一套分布式的高速缓存系统,由LiveJournal的Brad Fitzpatrick开发,但目前被许多网站使用以提升网站的访问速度,尤其对于一些大型的.需要频繁访 ...

  9. BugPhobia开发篇章:Beta阶段第VIII次Scrum Meeting

    0x01 :Scrum Meeting基本摘要 Beta阶段第八次Scrum Meeting 敏捷开发起始时间 2015/12/22 00:00 A.M. 敏捷开发终止时间 2015/12/22 23 ...

  10. 20135323符运锦----LINUX第三次实践:程序破解

    程序破解 一.掌握NOP.JNE.JE.JMP.CMP汇编指令的机器码 ①NOP:NOP指令即"空指令".执行到NOP指令时,CPU什么也不做,仅仅当做一个指令执行过去并继续执行N ...