BZOJ4541 HNOI2016矿区(平面图转对偶图)
考虑先将平面图转化为对偶图。具体地,将无向边拆成两条有向边。每次考虑找到包围一个区域的所有边。对当前考虑的边,找到该边的反向边在该边终点的出边集中,按极角序排序的后继,这条后继边也是包围该区域的边。这样对偶图就建好了。
考虑怎么用对偶图解决原问题。将外围的无限域也作为对偶图中的一个点,以其为根随便找一棵生成树,计算子树内面积和及面积平方和。对于询问,考虑多边形上每条边,其同时也是对偶图中两点的边。如果该边在生成树中是非树边,扔掉不管;如果是树边,若由父亲指向儿子,则加上儿子权值,否则减掉儿子权值。具体只能感性理解。
注意对偶图中两点间可能有重边,判断是否为非树边时小心一点。因为这个调一年也是没谁了。
#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矿区(平面图转对偶图)的更多相关文章
- [BZOJ4541][HNOI2016]矿区(平面图转对偶图)
https://www.cnblogs.com/ljh2000-jump/p/6423399.html #include<cmath> #include<vector> #in ...
- BZOJ 4541: [Hnoi2016]矿区 平面图转对偶图+DFS树
4541: [Hnoi2016]矿区 Time Limit: 30 Sec Memory Limit: 512 MBSubmit: 433 Solved: 182[Submit][Status][ ...
- BZOJ4541 [Hnoi2016]矿区
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...
- [HNOI2016]矿区
[HNOI2016]矿区 平面图转对偶图 方法: 1.分成正反两个单向边,每个边属于一个面 2.每个点按照极角序sort出边 3.枚举每一个边,这个边的nxt就是反边的前一个(这样找到的是面的边逆时针 ...
- LOJ#2052. 「HNOI2016」矿区(平面图转对偶图)
题面 传送门 题解 总算会平面图转对偶图了-- 首先我们把无向边拆成两条单向边,这样的话每条边都属于一个面.然后把以每一个点为起点的边按极角排序,那么对于一条边\((u,v)\),我们在所有以\(v\ ...
- bzoj 4541: [Hnoi2016]矿区【平面图转对偶图+生成树】
首先平面图转对偶图,大概思路是每条边存正反,每个点存出边按极角排序,然后找每条边在它到达点的出边中极角排序的下一个,这样一定是这条边所属最小多边形的临边,然后根据next边找出所有多边形,用三角剖分计 ...
- 【LG3249】[HNOI2016]矿区
[LG3249][HNOI2016]矿区 题面 洛谷 题解 先平面图转对偶图, 建好了对偶图之后随意拿出一个生成树,以无边界的范围为根. 无边界的范围很好求,用叉积算出有向面积时,算出来是负数的就是无 ...
- 【BZOJ-2007】海拔 最小割 (平面图转对偶图 + 最短路)
2007: [Noi2010]海拔 Time Limit: 20 Sec Memory Limit: 552 MBSubmit: 2095 Solved: 1002[Submit][Status] ...
- 平面图转对偶图(Bzoj1001:狼抓兔子)
如果只会用最小割做这道题那就太菜辣 引入 来自某学长 平面图:在平面上边不相交的图(边可以绕着画) 那么平面图的边与边就围成了许多个区域(这与你画图的方式有关) 定义对偶图:把相邻的两个区域连上边,形 ...
随机推荐
- keystone系列五:keystone源码分析
六 keystone架构 6.1 Keystone API Keystone API与Openstack其他服务的API类似,也是基于ReSTFul HTTP实现的. Keystone API划分为A ...
- [01] Why Spring
1.何为框架 简单来说,框架就是制定了一套规范或者规则(思想),让程序员在该规范或规则下进行工作.如上图修楼房,在有框架的情况下,修建工作才高效且有条不紊.楼层钢架规定了大楼的结构,工人按架构添砖放瓦 ...
- [07] 使用注解完成IOC配置
1.扫描配置 之前使用的Spring的Bean管理都是通过xml的配置文件来操作的,在Spring3.0之后已经引入了注解形式,Spring可以在指定路径下进行扫描,寻找标注了@Component.@ ...
- 解析LED发光效率
解析LED发光效率 来源:--作者:--浏览:532时间:2016-08-10 14:18 关键词: 发光效率为评测光源效率的指标,用光源发出的光通量 (lm)与向光源输入的电力(W)之比表示.单位为 ...
- 【SDOI2017】数字表格
题面 题解 这道题目还有一种比较有意思的解法. 定义一种运算\((\mathbf f\oplus\mathbf g)(x) = \prod\limits_{d\mid x}\mathbf f(d)^{ ...
- ElasticSearch实践系列(一):安装
Elasticsearch简介 Elasticsearch是一个高度可扩展的开源全文搜索和分析引擎.它允许您快速,近实时地存储,搜索和分析大量数据.它通常用作底层引擎/技术,为具有复杂搜索功能和要求的 ...
- 基于Angular+WebAPI+OData的增删改查
对于在ASP.NET WebAPI中怎么使用OData,已经在我前面的日志中的说明, 在ASP.NET Web API中使用OData 在这个示例中.我新建了一个Order的实体,在前端使用Angul ...
- cgroup.conf系统初始配置
# Slurm cgroup support configuration file # # See man slurm.conf and man cgroup.conf for further # i ...
- linux下向一个文件中的某行插入数据的做法
sed -i 'ni\x' test.file 表示向test.file文件里的第n行的前面添加x内容sed -i 'na\x' test.file 表示向test.file ...
- python基础学习笔记(十三)
re模块包含对 正则表达式.本章会对re模块主要特征和正则表达式进行介绍. 什么是正则表达式 正则表达式是可以匹配文本片段的模式.最简单的正则表达式就是普通字符串,可以匹配其自身.换包话说,正则表达式 ...