【loj3056】【hnoi2019】多边形
题目
描述
给出一个 \(n\) 个点的多边形初始的三角剖分;
一次合法的旋转定义为 \((a,b,c,d)\) ,满足 \(a<b<c<d\) ;
并且存在边\((a,b)(b,c)(c,d)(d,a)(a,c)\) ,将 \((a,c) - > (b,d)\) ;
简化后用\((a,c)\)描述一次旋转;
给出 \(m\) 个旋转操作,表示每次从初始状态 \(S_0\) 旋转成 \(S_i\) ;
询问对于 \(S_0 - S_m\) 到不能旋转的最少的步数以及方案数;
范围
$ 3 \le n \le 10^5 , 0 \le m \le 10^5 $ ;
题解
无法再旋转的情况为所有点的某一个端点都是 \(n\) , 否则所有连向 \(n\) 的边会将所有的多边形划分成很多部分,每个部分相互独立,并且每个部分里面一定可以再次移动。我们知道答案的一个下界是两个端点都不为 \(n\) 的线段条数,这个下界是可以达到的:可以发现每部分里面所有的区间形成了一个二叉树的结构,每次从根节点开始操作旋转,可以直接让根的某个端点到 \(n\),此时左右次数变成了新的两个独立的部分,再继续操作其左右子树。
接下来将每条连线 \((a,b)\) 看成线段,单调栈求出这个二叉树森林,显然最小步数==节点数 。 考虑方案,对于每一个二叉树,先转子树是无效的。所以合法的方案=> <优先选根,再选左右子树> 方案数是 。将二叉森林组合起来类似地乘以一个组合数即可;
加入修改,对于一次从 \(S_0\) 的改变,对旋转线段对应的点 \(u\) ,分两种情况讨论:
- \(u\) 为某个二叉树的根,最小次数--,删去根,左右儿子被分裂成了两个新的子树统计方案;
- 否则由于要合法一定是父亲的左儿子,最小次数不变,left-rotate(u) 之后统计方案(可以自己画图。。);
均可以只考虑变化量 \(O(1)\) 做到,考虑到要lower_bound旋转线段的标号:\(O(n \log n)\) ;
最近状态好迷啊,交了一发$WA $ 了,改了半天发现没取模TAT,点开博客看看其他人的做法发现yyb神仙也没有取模OVO ;
#include<bits/stdc++.h> #define ll long long using namespace std; const int N=200010,mod=1e9+7; int Case,n,m,cnt,st[N],top,ls[N],rs[N],fa[N],sz[N],id[N],pre=1,fac[N],inv[N],iv[N]; struct data{int l,r;data(int _l=0,int _r=0):l(_l),r(_r){};bool operator <(const data&A)const{return r==A.r?l>A.l:r<A.r;} }A[N]; char gc(){static char*p1,*p2,s[1000000];if(p1==p2)p2=(p1=s)+fread(s,1,1000000,stdin);return(p1==p2)?EOF:*p1++; } int rd(){int x=0;char c=gc();while(c<'0'||c>'9')c=gc();while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+c-'0',c=gc();return x; } char ps[1000000],*pp=ps; void push(char x){if(pp==ps+1000000)fwrite(ps,1,1000000,stdout),pp=ps;*pp++=x; } void flush(){fwrite(ps,1,pp-ps,stdout);pp=ps;} void write(int x){static int sta[20],top;if(!x){push('0');return;}while(x)sta[++top]=x%10,x/=10;while(top)push(sta[top--]^'0'); } int cal(int x,int y){return 1ll*fac[x+y]*inv[x]%mod*inv[y]%mod;} int ical(int x,int y){return 1ll*inv[x+y]*fac[x]%mod*fac[y]%mod;} void pushup(int x){int l=ls[x],r=rs[x];sz[x]=sz[l]+sz[r]+1;pre=1ll*pre*cal(sz[l],sz[r])%mod; } int mfy1(int x){int re=pre,l=ls[x],r=rs[x];re=1ll*re*ical(cnt-sz[x],sz[x])%mod*ical(sz[l],sz[r])%mod;re=1ll*re*cal(cnt-sz[x],sz[l])%mod*cal(cnt-1-sz[r],sz[r])%mod;return re; } int mfy2(int x){int re=pre,y=fa[x];re=1ll*re*ical(sz[ls[y]],sz[rs[y]])%mod*ical(sz[ls[x]],sz[rs[x]])%mod;re=1ll*re*cal(sz[y]-1-sz[ls[x]],sz[ls[x]])%mod*cal(sz[rs[x]],sz[rs[y]])%mod; return re; } int main(){ // freopen("polygon.in","r",stdin); // freopen("polygon.out","w",stdout);Case=rd();n=rd();iv[1]=1;for(int i=2;i<=n;++i)iv[i]=(ll)(mod-mod/i)*iv[mod%i]%mod;for(int i=fac[0]=inv[0]=1;i<=n;++i){fac[i]=(ll)fac[i-1]*i%mod; inv[i]=(ll)inv[i-1]*iv[i]%mod;}for(int i=1;i<=n-3;++i){A[i].l=rd(),A[i].r=rd();if(A[i].l>A[i].r)swap(A[i].l,A[i].r);}sort(A+1,A+n-2);for(int i=1;i<=n-3;++i){if(A[i].r==n)break;id[i]=++cnt;while(top&&A[st[top]].l>=A[i].l){if(A[st[top]].l==A[i].l)ls[cnt]=id[st[top--]],fa[ls[cnt]]=cnt;else rs[cnt]=id[st[top--]],fa[rs[cnt]]=cnt;}pushup(cnt);st[++top]=i;}for(int i=1,tmp=0;i<=top;++i){int t=sz[id[st[i]]];pre=1ll*pre*cal(tmp,t)%mod;tmp+=t;}m=rd();write(cnt);if(Case){push(' ');write(pre);}push('\n');for(int i=1,x,y,p,ans1,ans2;i<=m;++i){x=rd(),y=rd();if(x>y)swap(x,y);p = id[ lower_bound(A+1,A+n-2,data(x,y)) - A ];if(!fa[p]){ans1=cnt-1;ans2=mfy1(p);}else {ans1=cnt;ans2=mfy2(p);}write(ans1);if(Case){push(' ');write(ans2);}push('\n');}flush();return 0; }
转载于:https://www.cnblogs.com/Paul-Guderian/p/10683295.html
【loj3056】【hnoi2019】多边形相关推荐
- [loj3056][hnoi2019]多边形
前言 模数打错导致在模拟赛时变成40分 题目相关 链接 题目大意 给定一个多边形的三角划分 定义一个旋转操作为对于四个有边相连的点a<b<c<da<b<c<da&l ...
- Python+OpenCV 图像处理系列(3)—— 画线、矩形、画圆、画椭圆、画多边形
OpenCV 中的绘图函数 使用 OpenCV 绘制不同几何图形,其中包括的函数有 cv2.line() cv2.circle() cv2.rectangle() cv2.ellipse() cv2. ...
- 绘制多边形_XDGE_RayMarchine 1- 利用Frag Shader绘制图形
转载于小道的博客园 XDGE_RayMarchine 1- 利用Frag Shader绘制图形www.cnblogs.com # Render/RayMarchine/Base 1- 利用Frag绘 ...
- matlab 填充 多边形,algorithm – 如何在MATLAB中从无序边数据创建填充多边形?
如果多边形为 convex,则可以使用函数 CONVHULL从顶点计算凸包,并使用绘图函数 PATCH绘制多边形.例如: x = [0 1 0 1]; %# Unordered x coordinat ...
- 《OpenCV3编程入门》学习笔记8 图像轮廓与图像分割修复(三)使用多边形将轮廓包围
8.3 使用多边形将轮廓包围 8.3.1 将轮廓包围的多边形函数 1.返回外部边界:boundingRect()函数 (1)作用:返回指定点集最外面的边界矩形(四个顶点) (2)函数原型:Rect b ...
- 使用Python,OpenCV进行涂鸦(绘制文字、线、圆、矩形、椭圆、多边形轮廓、多边形填充、箭头~)
使用Python,OpenCV进行涂鸦(绘制文字.线.圆.矩形.椭圆.多边形轮廓.多边形填充.箭头) 1. 效果图 2. 原理 2.1 绘制线:cv2.line(canvas, (300, 0), ( ...
- Blender从头到尾创建低多边形角色学习教程 Low Poly Characters – Blender Bitesize Course
从头到尾创建低多边形角色. 你会学到: Blender界面的基础. 基本建模技术. 如何遵循字符引用? 如何创造和塑造自己的角色(不同风格.发型和服装). 纹理字符. 索具和动画介绍(用于你的游戏引擎 ...
- 在Blender中创建惊人的低多边形动画
大小解压后:13.5G 持续时间10小时+ 包括项目文件 1920X1080 MP4 语言:英语+中英文字幕(根据原英文字幕机译更准确) 标题:CGBoost学院–立方体世界在Blender中创建惊人 ...
- Blender从头开始装配和动画制作低多边形风格的FPS手臂
Rigging and Animating Low Poly FPS Arms in Blender MP4 |视频:h264,1280×720 |音频:AAC,44.1 KHz,2 Ch 语言:英语 ...
最新文章
- palm基础----7 获取系统信息
- c++运行不出结果_fastjson 不出网利用总结
- phpsduty环境下,使用composer安装报错
- C++学习之路 | PTA乙级—— 1032 挖掘机技术哪家强 (20 分)(精简)
- Visual C++ 2008入门经典 第四章数组 字符串(练习题)
- Pandas中Series和DataFrame的索引
- oem718d 基准站设置_诺瓦泰NovAtel OEM718D全系统多频单机测向板卡
- 机器学习 --- 3. 贝叶斯怎么想?(转)
- LAMMPS分子动力学模拟技术与应用 第一性原理计算方法及应用
- dell 服务器自动更新驱动程序,通过Repository Manager 1.3来管理戴尔驱动程序更新
- Java图像处理方面的工具库和开发包
- 计算机基础知识文件的复制移动,如何复制文件
- java:获取两个日期相隔天数
- BNU 看风景 27585
- 国内常见的IT认证都有哪些?这几个入大厂必备
- 如何组建局域网,用组和域管理分别是怎样设置的?
- 三十八载,Oracle伴我同行—记我的职业成长之路
- 论文阅读 | Asymmetric Bilateral Motion Estimation for Video Frame Interpolation
- 测测你是什么人格,C++代码程序,心理学,十分准确
- 东南大学数学系2010-2016年考研报录比【汇总】
热门文章
- 自动基线校正 python_安全运维中基线检查的自动化之ansible工具巧用
- 江苏职称计算机考试错做题,江苏省职称计算机考试word注意点.doc
- hssfwork 导出excel 文件已损坏_C# NPOI 操作EXCEL文件的读取和导出
- wpf messagebox.show()点击其他地方会闪烁_定时、童锁、故障查询,线控器上的这些功能你会用吗?...
- css3hlsa,CSS3颜色,文字,文本部分常用属性
- linux备份数据库软件有哪些内容,Linux网络备份MySQL数据库的应用方法
- CNN训练可视化特征图(tensorflow2.x实现)
- Node JS环境设置– Node.js安装
- 重置PL/SQL Developer工具栏布局
- 开课吧:浅析HTML5高薪的原因所在