LOJ#2052. 「HNOI2016」矿区(平面图转对偶图)
题面
题解
总算会平面图转对偶图了……
首先我们把无向边拆成两条单向边,这样的话每条边都属于一个面。然后把以每一个点为起点的边按极角排序,那么对于一条边\((u,v)\),我们在所有以\(v\)为起点的边中找到\((v,u)\)的前缀,这条边就是\((u,v)\)的下一条边了。不断重复这个过程直到找到的区域封闭为止
建好对偶图之后,我们对于每一个点,算出这个点所代表的区域的面积。对于无界域(就是外围无限的那个面),它的面积会是一个负数。那么我们找到这个无界域代表的节点之后,以它为根,求出对偶图的一棵生成树,并记录一下子树里的矿区面积和以及矿区面积平方和
然后考虑询问,对于每一条出现的边,如果是非树边就忽略,否则如果这条边所在的面是它的反边所在的面的儿子,我们就加上这个子树的贡献。否则就减去反边所在的面的子树的贡献。这个画一画图应该就出来了
//minamoto
#include<bits/stdc++.h>
#define R register
#define ll long long
#define pb push_back
#define IT vector<Eg>::iterator
#define inline __inline__ __attribute__((always_inline))
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
using namespace std;
char buf[1<<21],*p1=buf,*p2=buf;
inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
int read(){
R int res,f=1;R char ch;
while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
return res*f;
}
char sr[1<<21],z[20];int C=-1,Z=0;
inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
void print(R ll x){
if(C>1<<20)Ot();if(x<0)sr[++C]='-',x=-x;
while(z[++Z]=x%10+48,x/=10);
while(sr[++C]=z[Z],--Z);sr[++C]=' ';
}
const int N=2e5+5,M=1.2e6+5;const double eps=1e-10;
inline int sgn(R double x){return x<-eps?-1:x>eps;}
inline double abs(R double x){return x<-eps?-x:x;}
struct node{
int x,y;
inline node(){}
inline node(R int xx,R int yy):x(xx),y(yy){}
inline node operator +(const node &b)const{return node(x+b.x,y+b.y);}
inline node operator -(const node &b)const{return node(x-b.x,y-b.y);}
inline ll operator *(const node &b)const{return 1ll*x*b.y-1ll*y*b.x;}
}p[N];
struct Eg{
int id,u,v;double ang;
inline Eg(){}
inline Eg(R int ii,R int uu,R int vv,R double aa=0){id=ii,u=uu,v=vv,ang=aa;}
inline bool operator <(const Eg &b)const{return sgn(ang-b.ang)?ang<b.ang:v<b.v;}
}e[M];vector<Eg>h[N],tr[M];int tot=1,cnt,rt;IT it;
int nxt[M],pos[M],fa[M],vis[M],is[M],st[M];ll s[M],ss[M],ans1,ans2;
int n,q,m,top;
void add(R int u,R int v){
++tot,e[tot]=Eg(tot,u,v,atan2(p[v].y-p[u].y,p[v].x-p[u].x));
h[u].pb(e[tot]);
}
void build(){
fp(i,1,n)sort(h[i].begin(),h[i].end());
for(R int i=2,v=e[i].v;i<=tot;++i,v=e[i].v){
it=lower_bound(h[v].begin(),h[v].end(),e[i^1]);
if(it==h[v].begin())it=h[v].end();
nxt[i]=(--it)->id;
}
for(R int i=2;i<=tot;++i)if(!pos[i]){
pos[i]=pos[nxt[i]]=++cnt;
for(R int j=nxt[i],u=e[j].u,v=e[j].v;v!=e[i].u;j=nxt[j],pos[j]=cnt,u=e[j].u,v=e[j].v)
s[cnt]+=(p[u]-p[e[i].u])*(p[v]-p[e[i].u]);
if(s[cnt]<=0)rt=cnt;
}
fp(i,2,tot)tr[pos[i]].pb(Eg(i,pos[i],pos[i^1]));
}
void dfs(int u,int lst){
fa[u]=lst,ss[u]=s[u]*s[u],s[u]<<=1,vis[u]=1;
for(int i=0,sz=tr[u].size(),v;i<sz;++i){
v=tr[u][i].v;if(vis[v])continue;
is[tr[u][i].id]=is[tr[u][i].id^1]=1,dfs(v,u);
s[u]+=s[v],ss[u]+=ss[v];
}
}
int main(){
// freopen("testdata.in","r",stdin);
n=read(),m=read(),q=read();
fp(i,1,n)p[i].x=read(),p[i].y=read();
for(R int i=1,u,v;i<=m;++i)u=read(),v=read(),add(u,v),add(v,u);
build(),dfs(rt,0);
int u,v,w;Eg ee;ll g;
while(q--){
top=(read()+ans1)%n+1;
fp(i,1,top)st[i]=(read()+ans1)%n+1;
st[top+1]=st[1],ans1=ans2=0;
fp(i,1,top){
u=st[i],v=st[i+1];
ee=Eg(0,u,v,atan2(p[v].y-p[u].y,p[v].x-p[u].x));
it=lower_bound(h[u].begin(),h[u].end(),ee);
w=it->id;
if(!is[w])continue;
fa[pos[w]]==pos[w^1]?(ans1+=ss[pos[w]],ans2+=s[pos[w]]):(ans1-=ss[pos[w^1]],ans2-=s[pos[w^1]]);
}
g=__gcd(ans1,ans2),ans1/=g,ans2/=g;
print(ans1),print(ans2),sr[C]='\n';
}
return Ot(),0;
}
LOJ#2052. 「HNOI2016」矿区(平面图转对偶图)的更多相关文章
- 【LOJ】#2052. 「HNOI2016」矿区
题解 之前尝试HNOI2016的时候弃坑的一道,然后给补回来 (为啥我一些计算几何就写得好长,不过我写啥都长orz) 我们尝试给这个平面图分域,好把这个平面图转成对偶图 怎么分呢,我今天也是第一次会 ...
- loj #2051. 「HNOI2016」序列
#2051. 「HNOI2016」序列 题目描述 给定长度为 n nn 的序列:a1,a2,⋯,an a_1, a_2, \cdots , a_na1,a2,⋯,an,记为 a[1: ...
- 「HNOI2016」矿区
https://loj.ac/problem/2052 题解 平面图转对偶图.. 首先我们转的话需要给所有的平面标号,然后找到每条边看看他们隔开了哪两个平面. 做法就是对每个点维护它的所有排好序的出边 ...
- loj2052 「HNOI2016」矿区
学习一发平面图的姿势--ref #include <algorithm> #include <iostream> #include <cstdio> #includ ...
- loj#2049. 「HNOI2016」网络(set 树剖 暴力)
题意 题目链接 Sol 下面的代码是\(O(nlog^3n)\)的暴力. 因为从一个点向上只会跳\(logn\)次,所以可以暴力的把未经过的处理出来然后每个点开个multiset维护最大值 #incl ...
- LOJ #2048. 「HNOI2016」最小公倍数
题意 有 \(n\) 个点,\(m\) 条边,每条边连接 \(u \Leftrightarrow v\) 且权值为 \((a, b)\) . 共有 \(q\) 次询问,每次询问给出 \(u, v, q ...
- Loj #3056. 「HNOI2019」多边形
Loj #3056. 「HNOI2019」多边形 小 R 与小 W 在玩游戏. 他们有一个边数为 \(n\) 的凸多边形,其顶点沿逆时针方向标号依次为 \(1,2,3, \ldots , n\).最开 ...
- Loj #2192. 「SHOI2014」概率充电器
Loj #2192. 「SHOI2014」概率充电器 题目描述 著名的电子产品品牌 SHOI 刚刚发布了引领世界潮流的下一代电子产品--概率充电器: 「采用全新纳米级加工技术,实现元件与导线能否通电完 ...
- Loj #3096. 「SNOI2019」数论
Loj #3096. 「SNOI2019」数论 题目描述 给出正整数 \(P, Q, T\),大小为 \(n\) 的整数集 \(A\) 和大小为 \(m\) 的整数集 \(B\),请你求出: \[ \ ...
随机推荐
- PAT 1070 结绳(25)(代码)
1070 结绳(25 分) 给定一段一段的绳子,你需要把它们串成一条绳.每次串连的时候,是把两段绳子对折,再如下图所示套接在一起.这样得到的绳子又被当成是另一段绳子,可以再次对折去跟另一段绳子串连.每 ...
- 什么是RNA-Seq (RNA Sequencing)
什么是RNA-Seq (RNA Sequencing) 2011-07-14 ~ ADMIN 随着ome为词尾的各种组学的出现,转录组学已经成为了人们了解生物信息的一个重要组成部分.人们使用了许多办法 ...
- Debian Buster Nginx 布署 Brophp 项目(类 Thinkphp)
1 材料 debian buster nginx a project that develop base brophp 2 步骤 配置文件 /etc/nginx/sites-available/pis ...
- Storm 系列(一)基本概念
Storm 系列(一)基本概念 Apache Storm(http://storm.apache.org/)是由 Twitter 开源的分布式实时计算系统. Storm 可以非常容易并且可靠地处理无限 ...
- Spring.NET学习笔记8——集合类型的注入(基础篇)
1.基础类 public class Happy { public override string ToString() { return &q ...
- 导出jar文件
当我们编好一段代码时,就需要将其导出成应用程序,即jar文件(jar文件就是在Java运行环境下运行的应用程序).今天,巩固就教大家用eclipse导出jar文件. 第一步:找到eclipse,双击打 ...
- 2018.07.28 uoj#164. 【清华集训2015】V(线段树)
传送门 线段树好题. 要求支持的操作: 1.区间变成max(xi−a,0)" role="presentation" style="position: rela ...
- android 蓝牙通讯编程 备忘
1.启动App后: 判断->蓝牙是否打开(所有功能必须在打牙打开的情况下才能用) 已打开: 启动代码中的蓝牙通讯Service 未打开: 发布 打开蓝牙意图(系统),根据Activity返回进场 ...
- dj cookie & session组件
Cookie概述 什么叫Cookie Cookie翻译成中文是小甜点,小饼干的意思.在HTTP中它表示服务器送给客户端浏览器的小甜点.其实Cookie是key-value结构,类似于一个python中 ...
- IntelliJ IDEA 2017版 编译器使用学习笔记(一) (图文详尽版);IDE快捷键使用;IDE多行代码同时编写
IntellJ是一款强大的编译器,那么它有很多实用的功能 一.鼠标点击减少效率,快捷键实现各种跳转 (1)项目之间的跳转 快捷键位置: 操作:首先要有两个项目,然后,在不同窗口打开:如图: 然后使用快 ...