https://loj.ac/problem/2052

题解

平面图转对偶图。。

首先我们转的话需要给所有的平面标号,然后找到每条边看看他们隔开了哪两个平面。

做法就是对每个点维护它的所有排好序的出边,然后对于每一条有序边找到它的一条后继边。

如果一直找下去,就会找到一个平面,依次标号就好了。

我们转好了对偶图,\(dfs\)出对偶图的一颗生成树,然后对于一次询问,它肯定是切出了树上的一些联通块。

所以我们讨论一下每一条边的方向算一下答案就好了。

代码

#include<bits/stdc++.h>
#define N 200009
#define M 1200009
using namespace std;
typedef long long ll;
const double eps=1e-9;
int tot=1,n,m,q,pos[M],rt,b[N],nxt[M],num;
ll s[M],S[M],f[M];
bool ms[M],vis[M];
inline ll rd(){
ll x=0;char c=getchar();bool f=0;
while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();};
return f?-x:x;
}
struct point{
ll x,y;
inline point operator +(const point &b)const{return point{x+b.x,y+b.y};}
inline point operator -(const point &b)const{return point{x-b.x,y-b.y};}
inline ll operator *(const point &b)const{return x*b.y-y*b.x;}
}a[N];
struct edge{
int id,u,v;
double ang;
inline bool operator <(const edge &b)const{
if(fabs(ang-b.ang)>eps)return ang<b.ang;
}
}e[M];
vector<edge>vec[N];
vector<int>ed[M],ps[M];
inline void add(int x,int y){
++tot;e[tot]=edge{tot,x,y,atan2(a[y].y-a[x].y,a[y].x-a[x].x)};
vec[x].push_back(e[tot]);
}
inline void build(){
for(int i=1;i<=n;++i)sort(vec[i].begin(),vec[i].end());
for(int i=2;i<=tot;++i){
int id=e[i].v;
vector<edge>::iterator it=lower_bound(vec[id].begin(),vec[id].end(),e[i^1]);
if(it==vec[id].begin())it=vec[id].end();
--it;nxt[i]=it->id;
}
for(int i=2;i<=tot;++i)if(!pos[i]){
pos[i]=pos[nxt[i]]=++num;
int x=nxt[i];
while(1){
if(e[x].v==e[i].u)break;
s[num]+=(a[e[x].u]-a[e[i].u])*(a[e[x].v]-a[e[i].u]);
x=nxt[x];pos[x]=num;
}
if(s[num]<=0)rt=num,s[num]=0;
}
for(int i=2;i<=tot;++i)ed[pos[i]].push_back(pos[i^1]),ps[pos[i]].push_back(i);
}
void dfs(int u,int fa){
f[u]=fa;
S[u]=s[u]*s[u];s[u]<<=1;vis[u]=1;
for(int i=0;i<ed[u].size();++i){
int v=ed[u][i],tg=ps[u][i];
if(vis[v])continue;
ms[tg]=ms[tg^1]=1;
dfs(v,u);
S[u]+=S[v];s[u]+=s[v];
}
}
ll gcd(ll x,ll y){return y?gcd(y,x%y):x;}
void solve(){
ll ans1=0,ans2=0;
while(q--){
int x=(rd()+ans1)%n+1;
for(int i=1;i<=x;++i)b[i]=(rd()+ans1)%n+1;
ans1=ans2=0;
b[x+1]=b[1];
for(int i=1;i<=x;++i){
int xx=b[i],yy=b[i+1];
// cout<<xx<<" "<<ans1<<" "<<ans2<<" ";
edge z=edge{0,xx,yy,atan2(a[yy].y-a[xx].y,a[yy].x-a[xx].x)};
vector<edge>::iterator it=lower_bound(vec[xx].begin(),vec[xx].end(),z);
int j=it->id;
if(!ms[j])continue;
if(f[pos[j]]==pos[j^1])ans1+=S[pos[j]],ans2+=s[pos[j]];
else ans1-=S[pos[j^1]],ans2-=s[pos[j^1]];
}
ll g=gcd(ans1,ans2);
ans1/=g;ans2/=g;
printf("%lld %lld\n",ans1,ans2);
}
}
int main(){
n=rd();m=rd();q=rd();
int x,y;
for(int i=1;i<=n;++i){
x=rd();y=rd();
a[i]=point{x,y};
}
for(int i=1;i<=m;++i){
x=rd();y=rd();
add(x,y);add(y,x);
}
build();dfs(rt,0);solve();
return 0;
}

「HNOI2016」矿区的更多相关文章

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

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

  2. 【LOJ】#2052. 「HNOI2016」矿区

    题解 之前尝试HNOI2016的时候弃坑的一道,然后给补回来 (为啥我一些计算几何就写得好长,不过我写啥都长orz) 我们尝试给这个平面图分域,好把这个平面图转成对偶图 怎么分呢,我今天也是第一次会 ...

  3. loj2052 「HNOI2016」矿区

    学习一发平面图的姿势--ref #include <algorithm> #include <iostream> #include <cstdio> #includ ...

  4. 「HNOI2016」数据结构大毒瘤

    真是 \(6\) 道数据结构毒瘤... 开始口胡各种做法... 「HNOI2016」网络 整体二分+树状数组. 开始想了一个大常数 \(O(n\log^2 n)\) 做法,然后就被卡掉了... 发现直 ...

  5. 「HNOI2016」树 解题报告

    「HNOI2016」树 事毒瘤题... 我一开始以为每次把大树的子树再接给大树,然后死活不知道咋做,心想怕不是个神仙题哦 然后看题解后才发现是把模板树的子树给大树,虽然思维上难度没啥了,但是还是很难写 ...

  6. 「HNOI2016」序列 解题报告

    「HNOI2016」序列 有一些高妙的做法,懒得看 考虑莫队,考虑莫队咋移动区间 然后你在区间内部找一个最小值的位置,假设现在从右边加 最小值左边区间显然可以\(O(1)\),最小值右边的区间是断掉的 ...

  7. 「HNOI2016」网络 解题报告

    「HNOI2016」网络 我有一个绝妙的可持久化树套树思路,可惜的是,它的空间是\(n\log^2 n\)的... 注意到对一个询问,我们可以二分答案 然后统计经过这个点大于当前答案的路径条数,如果这 ...

  8. 「HNOI2016」最小公倍数 解题报告

    「HNOI2016」最小公倍数 考虑暴力,对每个询问,处理出\(\le a,\le b\)的与询问点在一起的联通块,然后判断是否是一个联通块,且联通块\(a,b\)最大值是否满足要求. 然后很显然需要 ...

  9. loj #2051. 「HNOI2016」序列

    #2051. 「HNOI2016」序列 题目描述 给定长度为 n nn 的序列:a1,a2,⋯,an a_1, a_2, \cdots , a_na​1​​,a​2​​,⋯,a​n​​,记为 a[1: ...

随机推荐

  1. Java基础语法—流程控制语句

    在一个程序执行的过程中,各条语句的执行顺序对程序的结果是有直接影响的.所以,我们必须清楚每条语句的执行流程.而且,很多时候要通过控制语句的执行顺序来实现我们想要的功能. 3.1 流程控制语句分类 ​ ...

  2. 【Linux 源码】Linux源码比较重要的目录

    (1)arch arch是architecture的缩写.内核所支持的每一种CPU体系,该目录下都有对应的子目录. 每个CPU的子目录,又进一步分解为boot.mm.kernel等子目录,分别包含控制 ...

  3. net 架构师-数据库-sql server-002-工具

    本章讲述的工具包括: SQL Server 联机丛书 SQL Server配置管理器 SQL Server Management Studio SQL Server Business Intellig ...

  4. mysql学习记录(一)

    #打开MySQL服务 sudo service mysql start #Ubuntu Linux 安装配置MySQL #安装MySQL服务器,核心程序 sudo apt-get install my ...

  5. [Codeforces 1228E]Another Filling the Grid (排列组合+容斥原理)

    [Codeforces 1228E]Another Filling the Grid (排列组合+容斥原理) 题面 一个\(n \times n\)的格子,每个格子里可以填\([1,k]\)内的整数. ...

  6. 小白学Python(20)—— Turtle 海龟绘图

    Turtle库是Python语言中一个很流行的绘制图像的函数库,想象一个小乌龟,在一个横轴为x.纵轴为y的坐标系原点,(0,0)位置开始,它根据一组函数指令的控制,在这个平面坐标系中移动,从而在它爬行 ...

  7. viewset的使用的方法

    viewset的使用方法中是怎么区分的update和crate modelViewSet中设置了这个类之后,设置了类成员变量:queryset 和 seriazlier class,所以POST操作直 ...

  8. nginx动静分离与网关

    当我们请求一个网页的时候,可能会加载很多css,js,img等静态文件:一般这些文件是很久都不会变化的,所以我们为了提高页面响应速度,完全可以将这些文件缓存到浏览器中(可以理解为cookie信息),这 ...

  9. JDK集合框架源码分析 - 简单概要

    1.类继承体系 在集合框架的类继承体系中,最顶层有两个接口Collection.Map: Collection 表示一组纯数据 Map 表示一组key-value对 Collection的类继承体系: ...

  10. 攻防世界--CGfsb238

    测试文件:https://adworld.xctf.org.cn/media/task/attachments/5982010c172744c8a1c93c24b5200b21 1.格式化字符串漏洞 ...