4541: [Hnoi2016]矿区
学习了一下平面图剖分的姿势,orz cbh
每次只要随便选择一条边,然后不停尽量向左转就行
- #include <bits/stdc++.h>
- #define N 1300000
- #define M 5000013
- #define LL long long
- #define pb push_back
- using namespace std;
- LL n, m, k;
- struct point
- {
- LL x, y;
- } S[N];
- vector <LL> bi[N];
- vector <LL> re[N], vis[N], s1[N], s2[N];
- vector <LL> bt[N], ca[N], cb[N];
- LL tot_are;
- LL siz[N], sum1[N], sum2[N], tot[N];
- LL nwc;
- LL comp(LL a, LL b)
- {
- return atan2(S[a].y - S[nwc].y, S[a].x - S[nwc].x) > atan2(S[b].y - S[nwc].y, S[b].x - S[nwc].x);
- }
- LL getsiz(point a, point b, point c)
- {
- return (b.x - a.x) * (c.y - a.y) - (c.x - a.x) * (b.y - a.y);
- }
- namespace addr
- {
- LL hs[M]; LL dt[M];
- LL get(LL a, LL b)
- {
- return 1ll * a * + b;
- }
- LL & find(LL a, LL b)
- {
- LL p = get(a, b); LL q = p % M;
- while (hs[q] && hs[q] != p) q = (q + ) % M;
- hs[q] = p; return dt[q];
- }
- }
- LL tvis[N], fa[N];
- void dfs(LL t)
- {
- //cout << t << "\n";
- tvis[t] = ;
- sum1[t] = siz[t] * siz[t];
- sum2[t] = siz[t] * ;
- for (LL i = ; i < bt[t].size(); ++ i)
- if (!tvis[bt[t][i]])
- {
- dfs(bt[t][i]); fa[bt[t][i]] = t;
- sum1[t] += sum1[bt[t][i]];
- sum2[t] += sum2[bt[t][i]];
- s1[ca[t][i]][addr :: find(ca[t][i], cb[t][i])] = sum1[bt[t][i]];
- s2[ca[t][i]][addr :: find(ca[t][i], cb[t][i])] = sum2[bt[t][i]];
- s1[cb[t][i]][addr :: find(cb[t][i], ca[t][i])] = -sum1[bt[t][i]];
- s2[cb[t][i]][addr :: find(cb[t][i], ca[t][i])] = -sum2[bt[t][i]];
- }
- }
- LL read()
- {
- LL x=,f=;char ch=getchar();
- while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
- while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
- return x*f;
- }
- LL c = ;
- int main()
- {
- //freopen("mine2.in", "r", stdin);
- n = read(); m = read(); k = read();
- for (LL i = ; i <= n; ++ i) S[i].x = read(), S[i].y = read();
- for (LL i = ; i <= m; ++ i)
- {
- LL a, b;
- a = read(); b = read();
- bi[a].push_back(b);
- bi[b].push_back(a);
- }
- for (LL i = ; i <= n; ++ i) re[i].resize(bi[i].size()), s1[i] = s2[i] = vis[i] = re[i];
- for (LL i = ; i <= n; ++ i) nwc = i, sort(bi[i].begin(), bi[i].end(), comp);
- for (LL i = ; i <= n; ++ i)
- for (LL j = ; j < bi[i].size(); ++ j)
- addr :: find(i, bi[i][j]) = j;
- for (LL i = ; i <= n; ++ i)
- for (LL j = ; j < bi[i].size(); ++ j)
- re[i][j] = addr :: find(bi[i][j], i);
- for (LL i = ; i <= n; ++ i)
- for (LL j = ; j < bi[i].size(); ++ j)
- if (!vis[i][j])
- {
- tot_are ++;
- for (LL k = i, p = j; !vis[k][p]; )
- {
- siz[tot_are] += getsiz(S[i], S[k], S[bi[k][p]]);
- vis[k][p] = tot_are;
- LL np = (re[k][p] + ) % bi[bi[k][p]].size();
- k = bi[k][p];
- p = np;
- }
- if (siz[tot_are] < ) c = tot_are;
- }
- for (LL i = ; i <= n; ++ i)
- for (LL j = ; j < bi[i].size(); ++ j)
- bt[vis[i][j]].push_back(vis[bi[i][j]][re[i][j]]),
- ca[vis[i][j]].push_back(i),
- cb[vis[i][j]].push_back(bi[i][j]);
- dfs(c);
- for (LL i = , last = ; i <= k; ++ i)
- {
- LL d, ns1 = , ns2 = ;
- d = read(); d = (d + last) % n + ;
- LL fs, ls, nw;
- fs = read(); fs = (fs + last) % n + ; ls = fs;
- for (LL j = ; j <= d; ++ j, ls = nw)
- {
- nw = read(); nw = (nw + last) % n + ;
- ns1 += s1[ls][addr :: find(ls, nw)];
- ns2 += s2[ls][addr :: find(ls, nw)];
- }
- ns1 += s1[ls][addr :: find(ls, fs)];
- ns2 += s2[ls][addr :: find(ls, fs)];
- LL g = __gcd(ns1, ns2);
- cout << ns1 / g << " " << ns2 / g << "\n";
- last = ns1 / g;
- }
- }
放在class里的东西还会爆栈QAQ,以后不敢用了
4541: [Hnoi2016]矿区的更多相关文章
- BZOJ 4541: [Hnoi2016]矿区 平面图转对偶图+DFS树
4541: [Hnoi2016]矿区 Time Limit: 30 Sec Memory Limit: 512 MBSubmit: 433 Solved: 182[Submit][Status][ ...
- ●BZOJ 4541 [Hnoi2016]矿区
题链: http://www.lydsy.com/JudgeOnline/problem.php?id=4541 题解: 平面图的对偶图,dfs树 平面图的对偶图的求法: 把所有双向边拆为两条互为反向 ...
- bzoj 4541: [Hnoi2016]矿区【平面图转对偶图+生成树】
首先平面图转对偶图,大概思路是每条边存正反,每个点存出边按极角排序,然后找每条边在它到达点的出边中极角排序的下一个,这样一定是这条边所属最小多边形的临边,然后根据next边找出所有多边形,用三角剖分计 ...
- [HNOI2016]矿区
[HNOI2016]矿区 平面图转对偶图 方法: 1.分成正反两个单向边,每个边属于一个面 2.每个点按照极角序sort出边 3.枚举每一个边,这个边的nxt就是反边的前一个(这样找到的是面的边逆时针 ...
- 【LG3249】[HNOI2016]矿区
[LG3249][HNOI2016]矿区 题面 洛谷 题解 先平面图转对偶图, 建好了对偶图之后随意拿出一个生成树,以无边界的范围为根. 无边界的范围很好求,用叉积算出有向面积时,算出来是负数的就是无 ...
- BZOJ4541 [Hnoi2016]矿区
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...
- 【bzoj4541】 Hnoi2016—矿区
http://www.lydsy.com/JudgeOnline/problem.php?id=4541 (题目链接) 题意 给出一个平面图,若干询问,每次询问一个凸多边形内小多边形面积的平方和与面积 ...
- BZOJ4541 HNOI2016矿区(平面图转对偶图)
考虑先将平面图转化为对偶图.具体地,将无向边拆成两条有向边.每次考虑找到包围一个区域的所有边.对当前考虑的边,找到该边的反向边在该边终点的出边集中,按极角序排序的后继,这条后继边也是包围该区域的边.这 ...
- [BZOJ4541][HNOI2016]矿区(平面图转对偶图)
https://www.cnblogs.com/ljh2000-jump/p/6423399.html #include<cmath> #include<vector> #in ...
随机推荐
- [LeetCode] First Unique Character in a String 字符串第一个不同字符
Given a string, find the first non-repeating character in it and return it's index. If it doesn't ex ...
- [LeetCode] Word Search 词语搜索
Given a 2D board and a word, find if the word exists in the grid. The word can be constructed from l ...
- ServerSocket的介绍
导语 仅仅只有Socket类是不足以编写服务器的.要创建一个Socket,你需要知道希望连接哪个Internet主机.编写服务器程序时,无法预先了解哪个主机会联系你,即使确实知道,你也不清楚那个主机希 ...
- 记录rewrite url我之前不知道的地方
大部分url重写的需求是伪静态,当然有很多第三方开源组件,但是这种需求的核心方法其实就是context.rewritePath() 要是系统像ARR那样,用重写做代理和反向代理,一般的重写就不行了,c ...
- ubuntu下的apt-get内网本地源的搭建
APT本地源的搭建(可用于局域网apt-get源搭建或者本地源) 本文档介绍使用apt-mirror软件搭建apt本地源 需求:内网开发环境由于其特定原因不能上外网,所以需要本地环境下的内网源来方便开 ...
- 【BZOJ 1005】【HNOI 2008】明明的烦恼
http://www.lydsy.com/JudgeOnline/problem.php?id=1005 答案是\[\frac{(n-2)!}{(n-2-sum)!×\prod_{i=1}^{cnt} ...
- PAT Basic Level 1001
大纲考察内容 数据存储结构:数组.链 基础算法:递归.排序.计算时间复杂度.空间复杂度.分析算法稳定性 1001.害死人不偿命的(3n+1)猜想 (15) https://www.patest.cn/ ...
- Java开发实践 集合框架 全面分析
http://www.open-open.com/lib/view/open1474167415464.html
- Python OOP(面向对象编程)
一OOP的作用 在Python中,类是面向对象设计(OOP)的主要工具.通过使用类这种工具,OOP可以: 1.分解代码,最小化代码的冗余. 2.通过定制现有的代码,来编写新的程序,而不用在原处进行修改 ...
- bootstrap学习笔记--bootstrap排版类的使用
标题 Bootstrap 中定义了所有的 HTML 标题(h1 到 h6)的样式,这个和一般的html没啥区别.请看下面的实例: <h1>测试1 h1</h1> <h2& ...