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:狼抓兔子)
如果只会用最小割做这道题那就太菜辣 引入 来自某学长 平面图:在平面上边不相交的图(边可以绕着画) 那么平面图的边与边就围成了许多个区域(这与你画图的方式有关) 定义对偶图:把相邻的两个区域连上边,形 ...
随机推荐
- IIR数字滤波器的实现(C语言)
经典滤波器和数字滤波器 一般滤波器可以分为经典滤波器和数字滤波器. 经典滤波器:假定输入信号中的有用成分和希望去除的成分各自占有不同的频带.如果信号和噪声的频谱相互重迭,经典滤波器无能为力.比如 FI ...
- 深入理解 JVM(上)
菜鸟拙见,望请纠正(首先:推荐一本书[链接:https://pan.baidu.com/s/15I062n5LPYtRmueAAUFuFA 密码:kyo1]) 一:JVM体系概述 1:JVM是运行在操 ...
- JS-JS代码插入位置
一.HTML 页面的 <head> 部分中 由于 HTML 文档是由浏览器从上到下依次载入的,将 JavaScript 代码放置于<head></head> 标签之 ...
- C#批量插入数据到Sqlserver中的四种方式 - 转
先创建一个用来测试的数据库和表,为了让插入数据更快,表中主键采用的是GUID,表中没有创建任何索引.GUID必然是比自增长要快的,因为你生成一个GUID算法所花的时间肯定比你从数据表中重新查询上一条记 ...
- BootStrap学习(6)_模态框
一.模态框 模态框(Modal)是覆盖在父窗体上的子窗体.通常,目的是显示来自一个单独的源的内容,可以在不离开父窗体的情况下有一些互动.子窗体可提供信息.交互等. 如果只使用该功能,只引入BootSt ...
- 01-时间复杂度、对数器(python)、冒泡、选择、递归实质、归并、小和问题、逆序对、mid
1.时间复杂度 常数时间的操作:一个操作如果和数据量没有关系,每次都是固定时间内完成的操作,叫做常数操作. 时间复杂度为一个算法流程中,常数操作数量的指标.常用O(读作big O)来表示. 具体来说, ...
- linux监控文件夹内的文件数量
开发的时候遇到一个问题,服务器一旦重启,项目生成的文件就丢失了,感觉很莫名其妙..一开始猜测是文件流没有关闭,检查了代码,感觉没毛病.于是先看看是关机丢失了文件还是开机被删除了.下面的脚本每秒执行一次 ...
- [UWP 自定义控件]了解模板化控件(2):模仿ContentControl
ContentControl是最简单的TemplatedControl,而且它在UWP出场频率很高.ContentControl和Panel是VisualTree的基础,可以说几乎所有VisualTr ...
- python-知识回顾-16
知识回顾 小数据池:int -5~256str 特殊字符,*数字20 ascii : 8位 1字节 表示1个字符unicode 32位 4个字节 表示一个字符utf- 8 1个英文 8位,1个字节 欧 ...
- Flask之WSGI:Werkzeug
WSGI 一个Web应用的本质就是: 浏览器发送一个HTTP请求: 服务器收到请求,生成一个HTML文档: 服务器把HTML文档作为HTTP响应的Body发送给浏览器: 浏览器收到HTTP响应,从HT ...