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. Golang中的error类型

    Golang中的error类型 error类型本身就是一个预定义好的接口,里面定义了一个method type error interface { Error() string } 生成一个新的err ...

  2. eclipse sts 常规操作

    项目:右键 refresh 右键 maven -> update project 重新remove add project    重启软件,电脑 1.项目冗余 Package Explorer ...

  3. Miller-Robin 素数测试法 模板

    测试单个素数,出错概率比计算机本身出错的概率还要低 算法是基于费马小定理(format),二次探测定理(x*x % p == 1 ,若P为素数,则x的解只能是x = 1或者x = p - 1)加上迭代 ...

  4. 使用ntpdate 同步 linux的时间

    1. linux 查看时间和时区的命令 timedatectl 效果为: Local time: Sun -- :: CST Universal time: Sun -- :: UTC RTC tim ...

  5. MySQL8 clone plugin

    安装MySQl8.0.17 下载 MySQL8.0.17 二进制版本 https://dev.mysql.com/downloads/mysql/ 解压,修改权限 -linux-glibc2.-x86 ...

  6. bits,Bytes,KB,MB,GB和TB之间的换算关系

    1Bytes=8bits(1字节等于8位) 1KB=1024Bytes(1KB等于1024字节) 1MB=1024KB 1GB=1024MB 1TB=1024GB 为啥带宽100M而下载大概只是12. ...

  7. C++中的函数重载分析(一)

    1,重载是 C 语言到 C++ 语言的一个飞跃,C 语言中没有重载的概念,所有的函数 名是不允许有重复的,在 C++ 中因为引进了重载,所以函数名可以重复: 2,自然语言中的上下文: 1,你知道上面词 ...

  8. Centos7防火墙开启3306端口

    CentOS7的默认防火墙为firewall,且默认是不打开的. systemctl start firewalld # 启动friewall systemctl status firewalld # ...

  9. django项目学习之QQ登录

    最近在用django框架写一个商城项目(前后端分离),里面用到的一些技术其他项目也可以借鉴,于是就想写一些博客记录,以防自己忘记,今天先写一个关于登录接口中引入QQ登录接口的流程. 关于QQ登录接口的 ...

  10. linux:shell脚本格式

    shell脚本格式:     #!/bin/bash //第一行指定bash     命令群.....          例子:     #!/bin/bash     DESCDIR='/tmp/t ...