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:狼抓兔子)
如果只会用最小割做这道题那就太菜辣 引入 来自某学长 平面图:在平面上边不相交的图(边可以绕着画) 那么平面图的边与边就围成了许多个区域(这与你画图的方式有关) 定义对偶图:把相邻的两个区域连上边,形 ...
随机推荐
- UI自动化测试模型
所谓的自动化测试模型,可以理解为自动化测试框架+工具设计的一种思想产物. 先说说库.框架.工具之间的区别: 库:英文名Library,由代码集成的一个产品,供用户调用.面向对象的库叫做类库,面向过程的 ...
- Unable to execute dex: Multiple dex files defineLcom/google/gson/JsonDeserializer;
这是异常想必大家都知道的,是关于一个android jar包冲突的问题.为什么还要提呢,是因为这玩意真心让人蛋疼.有些时候稍微不注意(手贱)多导入一个包,就完蛋了.(jar包多的话搞不好带一上午调试) ...
- Android ExpandableListView和ScrollView联用的一些注意事项
之前有整理过ScrollView嵌套ListView的例子,讲的是计算listview的每一项的高度.已达到目标效果.同样的ExpandableListView嵌套ScrollView也是这么个思路, ...
- Kubernetes 1.10.4 镜像 版本
1. gcr.io/google-containers/hyperkube:1.10.4 gcr.io/google_containers/pause-amd64:3.0 gcr.io/google_ ...
- BZOJ3676 APIO2014 回文串 Manacher、SA
传送门 首先一个结论:串\(S\)中本质不同的回文串个数最多有\(|S|\)个 证明考虑以点\(i\)结尾的所有回文串,假设为\(S[l_1,i],S[l_2,i],...,S[l_k,i]\),其中 ...
- (转)deb制作文件详解
转自:http://blog.chinaunix.net/uid-16184599-id-3041024.html 如何制作Deb包和相应的软件仓库,其实这个很简单.这里推荐使用dpkg来进行deb包 ...
- [Oracle]获得PDB相关的xml 文件
问题:客户进行了PDB的克隆之后,发现启动时出现: ORA-44777: Pluggable database service cannot be started. 分析手段: 为了获得PDB的相关信 ...
- 12.4 开课三个月(phpcms安装)
cms的样式有很多种,我们学习的是phpcms,这些cms都是大同小异,学会了一种就可以使用其它的cms. PHPCMS是一款网站管理软件.该软件采用模块化开发,支持多种分类方式,使用它可方便实现个性 ...
- 【转载】固态硬盘的S.M.A.R.T详解
文章来源于: 瑞耐斯存储技术 兵哥写这篇文章,是因为在测试的过程中看到了 SSD存在偶尔有性能下降的情况,经分析为S.M.A.R.T命令所导致,虽然这种情况看似不严重,但如果应用在诸如数据采集等关键性 ...
- Bash : IO 重定向
标准输入/输出(standard I/O)可能是软件设计原则里最重要的概念了.这个概念就是:程序应该有数据的来源端.数据的目的端(输出结果的地方)已经报告问题的地方,它们分别被称为标准输入(stand ...