【LG3249】[HNOI2016]矿区

时间:2022-09-24 13:57:53

【LG3249】[HNOI2016]矿区

题面

洛谷

题解

先平面图转对偶图,

建好了对偶图之后随意拿出一个生成树,以无边界的范围为根。

无边界的范围很好求,用叉积算出有向面积时,算出来是负数的就是无边界的范围。

然后标记所有的树边,记录生成树中每个子树的矿区面积和及面积平方和。

对于每一个询问,先找到询问里出现的边,如果有非树边就忽略,否则如果这条边所在的面是儿子,就加上子树的面积,如果是父亲就减去儿子子树的面积。

这个可以通过画图手玩进行证明。

代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
using namespace std;
inline int gi() {
register int data = 0, w = 1;
register char ch = 0;
while (!isdigit(ch) && ch != '-') ch = getchar();
if (ch == '-') w = -1, ch = getchar();
while (isdigit(ch)) data = 10 * data + ch - '0', ch = getchar();
return w * data;
}
const int MAX_N = 2e5 + 5, MAX_M = 1.2e6 + 5;
const double EPS = 1e-10;
struct Point { int x, y; } p[MAX_N];
Point operator - (const Point &l, const Point &r) { return (Point){l.x - r.x, l.y - r.y}; }
long long cross(const Point &l, const Point &r) { return 1ll * l.x * r.y - 1ll * l.y * r.x; }
struct Edge { int id, x, y; double a; } e[MAX_M]; int e_cnt = 0;
bool operator < (const Edge &l, const Edge &r)
{ return fabs(l.a - r.a) < EPS ? l.y < r.y : l.a < r.a; }
vector<Edge> G[MAX_N], T[MAX_M];
void Add_Edge(int u, int v) {
e[e_cnt] = (Edge){e_cnt, u, v, atan2(p[v].y - p[u].y, p[v].x - p[u].x)};
G[u].push_back(e[e_cnt]); e_cnt++;
}
int N, M, Q;
int cnt, root, nxt[MAX_M], pos[MAX_M], fa[MAX_M];
long long ans1, ans2, s1[MAX_M], s2[MAX_M];
void build() {
for (int i = 1; i <= N; i++) sort(G[i].begin(), G[i].end());
for (int i = 0; i < e_cnt; i++) {
int y = e[i].y;
vector<Edge> :: iterator ite = lower_bound(G[y].begin(), G[y].end(), e[i ^ 1]);
if (ite == G[y].begin()) ite = G[y].end();
--ite, nxt[i] = ite -> id;
}
for (int i = 0; i < e_cnt; i++) {
if (pos[i]) continue;
pos[i] = pos[nxt[i]] = ++cnt;
for (int j = nxt[i]; e[j].y != e[i].x; j = nxt[j], pos[j] = cnt)
s1[cnt] += cross(p[e[j].x] - p[e[i].x], p[e[j].y] - p[e[i].x]);
if (s1[cnt] <= 0) root = cnt;
}
for (int i = 0; i < e_cnt; i++)
T[pos[i]].push_back((Edge){i, pos[i], pos[i ^ 1]});
}
bool vis[MAX_M], ist[MAX_M];
void dfs(int x) {
s2[x] = 1ll * s1[x] * s1[x], s1[x] <<= 1ll, vis[x] = 1;
for (int i = 0, sz = T[x].size(); i < sz; i++) {
int y = T[x][i].y; if (vis[y]) continue;
ist[T[x][i].id] = ist[T[x][i].id ^ 1] = 1;
fa[y] = x; dfs(y); s1[x] += s1[y], s2[x] += s2[y];
}
}
long long gcd(long long x, long long y) {
if (y == 0) return x;
else return gcd(y, x % y);
}
int q[MAX_M];
int main () {
#ifndef ONLINE_JUDGE
freopen("cpp.in", "r", stdin);
#endif
N = gi(), M = gi(), Q = gi();
for (int i = 1; i <= N; i++) p[i] = (Point){gi(), gi()};
for (int i = 1; i <= M; i++) {
int u = gi(), v = gi();
Add_Edge(u, v), Add_Edge(v, u);
}
build(); dfs(root);
while (Q--) {
int n = (gi() + ans1) % N + 1;
for (int i = 1; i <= n; i++) q[i] = (gi() + ans1) % N + 1;
q[n + 1] = q[1], ans1 = ans2 = 0;
for (int i = 1; i <= n; i++) {
int x = q[i], y = q[i + 1];
Edge e = (Edge){0, x, y, atan2(p[y].y - p[x].y, p[y].x - p[x].x)};
vector<Edge> :: iterator ite = lower_bound(G[x].begin(), G[x].end(), e);
int j = ite -> id; if (!ist[j]) continue;
if (fa[pos[j]] == pos[j ^ 1]) ans1 += s2[pos[j]], ans2 += s1[pos[j]];
else ans1 -= s2[pos[j ^ 1]], ans2 -= s1[pos[j ^ 1]];
}
long long tmp = gcd(ans1, ans2);
ans1 /= tmp, ans2 /= tmp;
printf("%lld %lld\n", ans1, ans2);
}
return 0;
}

【LG3249】[HNOI2016]矿区的更多相关文章

  1. &lbrack;HNOI2016&rsqb;矿区

    [HNOI2016]矿区 平面图转对偶图 方法: 1.分成正反两个单向边,每个边属于一个面 2.每个点按照极角序sort出边 3.枚举每一个边,这个边的nxt就是反边的前一个(这样找到的是面的边逆时针 ...

  2. BZOJ 4541&colon; &lbrack;Hnoi2016&rsqb;矿区 平面图转对偶图&plus;DFS树

    4541: [Hnoi2016]矿区 Time Limit: 30 Sec  Memory Limit: 512 MBSubmit: 433  Solved: 182[Submit][Status][ ...

  3. BZOJ4541 &lbrack;Hnoi2016&rsqb;矿区

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...

  4. 4541&colon; &lbrack;Hnoi2016&rsqb;矿区

    学习了一下平面图剖分的姿势,orz cbh 每次只要随便选择一条边,然后不停尽量向左转就行 #include <bits/stdc++.h> #define N 1300000 #defi ...

  5. ●BZOJ 4541 &lbrack;Hnoi2016&rsqb;矿区

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=4541 题解: 平面图的对偶图,dfs树 平面图的对偶图的求法: 把所有双向边拆为两条互为反向 ...

  6. BZOJ4541 HNOI2016矿区(平面图转对偶图)

    考虑先将平面图转化为对偶图.具体地,将无向边拆成两条有向边.每次考虑找到包围一个区域的所有边.对当前考虑的边,找到该边的反向边在该边终点的出边集中,按极角序排序的后继,这条后继边也是包围该区域的边.这 ...

  7. &lbrack;BZOJ4541&rsqb;&lbrack;HNOI2016&rsqb;矿区&lpar;平面图转对偶图&rpar;

    https://www.cnblogs.com/ljh2000-jump/p/6423399.html #include<cmath> #include<vector> #in ...

  8. 【bzoj4541】 Hnoi2016—矿区

    http://www.lydsy.com/JudgeOnline/problem.php?id=4541 (题目链接) 题意 给出一个平面图,若干询问,每次询问一个凸多边形内小多边形面积的平方和与面积 ...

  9. bzoj 4541&colon; &lbrack;Hnoi2016&rsqb;矿区【平面图转对偶图&plus;生成树】

    首先平面图转对偶图,大概思路是每条边存正反,每个点存出边按极角排序,然后找每条边在它到达点的出边中极角排序的下一个,这样一定是这条边所属最小多边形的临边,然后根据next边找出所有多边形,用三角剖分计 ...

随机推荐

  1. 在Mac OS X中配置Apache + PHP + MySQL

    在Mac OS X中配置Apache + PHP + MySQL Mac OS X 内置Apache 和 PHP,使用起来非常方便.本文以Mac OS X 10.6.3和为例.主要内容包括: 启动Ap ...

  2. iOS开发之Socket通信实战--Request请求数据包编码模块

    实际上在iOS很多应用开发中,大部分用的网络通信都是http/https协议,除非有特殊的需求会用到Socket网络协议进行网络数 据传输,这时候在iOS客户端就需要很好的第三方CocoaAsyncS ...

  3. Hadoop 部署过程中的一些问题与解决方案

    环境--> centos7.1 --> jdk1.8 1.JDK卸载与安装 http://blog.csdn.net/czmchen/article/details/41047187 2. ...

  4. 三、Authentication &amp&semi; sessionid

    客户在访问Django的某些敏感资料时,被要求需要先登录,客户通过/admin/login进行登录,客户登录成功后,Django给客户分配一个sessionid,后续的访问过程,客户端只需在http头 ...

  5. 神奇的Noip模拟试题一试 2 排队

    2 排队 (lineup.pas/.c/.cpp) [问题描述] 小sin所在的班有n名同学,正准备排成一列纵队,但他们不想按身高从矮到高排,那样太单调,太没个性.他们希望恰好有k对同学是高的在前,矮 ...

  6. Codevs 1171 潜伏者 2009年NOIP全国联赛提高组

    1171 潜伏者 2009年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description [问题描述] R 国和S 国正陷 ...

  7. 如何使用SecureCRT连接vmware下ubuntu

    配置SecureCrt 和 ubuntu1. 首先要明白什么是ssh?可以把ssh看做是telnet的加强版,telnet的密码和信息都是不加密的,而ssh则加密.2. 开启ubuntu上的ssh功能 ...

  8. Linux下DVD-R刻录问题

    之前CD的刻录一直使用的命令行工具集cdrtools中的mkisofs.cdrecord.然后本来刻录DVD可以使用它的growisofs命令. 现在假设原始文件目录为/src/,目标目录为/dest ...

  9. Windows SVN变化邮件通知(Python2&period;7实现)

    1,新增文件post-commit.bat 内容: rem REPOS-PATH (the path to this repository) set REPOS=%1 rem REV (the num ...

  10. shell学习-读取输入

    功能:读取输入,打印:如果长度小于MINLEN,那么输出空格. #!/bin/bash # paragraph-space.sh # Insert a blank line between parag ...