原题传送门

HN的题目就是毒瘤

我们有以下猜想:

1.最后所有的线都连到了n号点上

2.最小步数应该为n-3-已经连到n号点的线段数量

本来有些边\((a_i,n)\)会将整个图分割成很多个区间。对于一个区间\([l,r]\),\(l,r\)之间必定存在一条边,并且一定存在点\(mid\)有\((mid,l),mid(mid,r)\)的边,所以我们珂以用一次旋转使得\((l,r)\)变成\((mid,n)\),这样这个区间有珂以分成两个子区间,珂以建出二叉树。一直如此,直到\(r=l+1\)为止。我们现在就要考虑如何计算方案数,父节点的旋转一定在子节点的旋转之前,但子节点间互不干扰,所以就是一个插入排序方案数的问题,明显两个子树顺序影响就是把答案乘上\(\frac{(size(ls)+size(rs))!}{size(ls)!size(rs)!}\)

最后要记得不同区间之间也有合并的贡献

我们现在要考虑修改:

1.\((a,c)\)旋转后正好为\((b,n)\),就相当于将一棵树根节点的两个子树作为新的树,并且删除原来的根节点,对最小步数的影响为-1,对次数的影响也很简单(此处就不赘述,不会的珂以看代码)

2.\((a,c)\)旋转后变成了\((b,d) (d \neq n)\),这个操作像splay的rotate,具体见图片,对最小步数没有影响,对次数的影响见代码

#include <bits/stdc++.h>
#define N 100005
#define mod 1000000007
#define getchar nc
using namespace std;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int read()
{
register int x=0,f=1;register char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return x*f;
}
inline void write(register int x)
{
if(!x)putchar('0');if(x<0)x=-x,putchar('-');
static int sta[20];register int tot=0;
while(x)sta[tot++]=x%10,x/=10;
while(tot)putchar(sta[--tot]+48);
}
inline int fastpow(register int a,register int b)
{
int res=1;
while(b)
{
if(b&1)
res=1ll*res*a%mod;
a=1ll*a*a%mod;
b>>=1;
}
return res;
}
vector<int> E[N];
inline void add(register int u,register int v)
{
E[u].push_back(v),E[v].push_back(u);
}
int W,n,m;
int fac[N],invf[N];
int fa[N],ls[N],rs[N],sz[N];
int tot=0,sum=0,ans=1;
map<pair<int,int>,int> M;
inline int calc(register int n,register int m)
{
return 1ll*fac[n+m]*invf[n]%mod*invf[m]%mod;
}
inline int calcinv(register int n,register int m)
{
return 1ll*invf[n+m]*fac[n]%mod*fac[m]%mod;
}
inline void dfs(register int &x,register int l,register int r,register int f)
{
if(l+1==r)
return;
x=++tot;
M[make_pair(l,r)]=x;
fa[x]=f;
int mid=*(--lower_bound(E[l].begin(),E[l].end(),r));
dfs(ls[x],l,mid,x),dfs(rs[x],mid,r,x);
sz[x]=sz[ls[x]]+sz[rs[x]]+1;
ans=1ll*ans*calc(sz[ls[x]],sz[rs[x]])%mod;
}
int main()
{
fac[0]=1;
for(register int i=1;i<N;++i)
fac[i]=1ll*fac[i-1]*i%mod;
invf[N-1]=fastpow(fac[N-1],mod-2);
for(register int i=N-1;i;--i)
invf[i-1]=1ll*invf[i]*i%mod;
W=read(),n=read();
for(register int i=1;i<n;++i)
add(i,i+1);
add(1,n);
for(register int i=1;i<=n-3;++i)
{
int u=read(),v=read();
add(u,v);
}
for(register int i=1;i<=n;++i)
sort(E[i].begin(),E[i].end());
for(register int i=0;i<E[n].size()-1;++i)
{
int x=0;
dfs(x,E[n][i],E[n][i+1],0);
ans=1ll*ans*calc(sum,sz[x])%mod;
sum+=sz[x];
}
if(W)
write(sum),putchar(' '),write(ans),puts("");
else
write(sum),puts("");
m=read();
while(m--)
{
int a=read(),b=read(),x=M[make_pair(a,b)];
if(fa[x])
{
int f=fa[x],now=ans;
now=1ll*now*calcinv(sz[ls[x]],sz[rs[x]])%mod;
now=1ll*now*calcinv(sz[ls[f]],sz[rs[f]])%mod;
now=1ll*now*calc(sz[rs[x]],sz[rs[f]])%mod;
now=1ll*now*calc(sz[ls[x]],sz[rs[x]]+sz[rs[f]]+1)%mod;
if(W)
write(sum),putchar(' '),write(now),puts("");
else
write(sum),puts("");
}
else
{
int now=ans;
now=1ll*now*calcinv(sz[ls[x]],sz[rs[x]])%mod;
now=1ll*now*calcinv(sum-sz[x],sz[x])%mod;
now=1ll*now*calc(sum-sz[x],sz[ls[x]])%mod;
now=1ll*now*calc(sum-sz[x]+sz[ls[x]],sz[rs[x]])%mod;
if(W)
write(sum-1),putchar(' '),write(now),puts("");
else
write(sum-1),puts("");
}
}
return 0;
}

【题解】Luogu P5288 [HNOI2019]多边形的更多相关文章

  1. luogu P5288 [HNOI2019]多边形

    传送门 这是什么神仙操作... 首先要注意一些性质.首先每一个\((x,n)\)的边可以把当前多边形分成两半,这两半的操作是独立的.然后对于某一个没有\((x,n)\)的边的多边形,最优操作是唯一的. ...

  2. HNOI2019 多边形 polygon

    HNOI2019 多边形 polygon https://www.luogu.org/problemnew/show/P5288 这题镪啊... 首先堆结论: 显然终止状态一定是所有边都连向n了 根据 ...

  3. 【BZOJ5491】[HNOI2019]多边形(模拟,组合计数)

    [HNOI2019]多边形(模拟,组合计数) 题面 洛谷 题解 突然特别想骂人,本来我考场现切了的,结果WA了几个点,刚刚拿代码一看有个地方忘记取模了. 首先发现终止态一定是所有点都向\(n\)连边( ...

  4. [题解] Luogu P5446 [THUPC2018]绿绿和串串

    [题解] Luogu P5446 [THUPC2018]绿绿和串串 ·题目大意 定义一个翻转操作\(f(S_n)\),表示对于一个字符串\(S_n\), 有\(f(S)= \{S_1,S_2,..., ...

  5. 【题解】Luogu P5294 [HNOI2019]序列

    原题传送门 题意:给你一个长度为\(n\)的序列\(A\),每次询问修改一个元素(只对当前询问有效),然后让你找到一个不下降序列\(B\),使得这两个序列相应位置之差的平方和最小,并输出这个最小平方和 ...

  6. 题解 Luogu P2499: [SDOI2012]象棋

    关于这道题, 我们可以发现移动顺序不会改变答案, 具体来说, 我们有以下引理成立: 对于一个移动过程中的任意一个移动, 若其到达的位置上有一个棋子, 则该方案要么不能将所有棋子移动到最终位置, 要么可 ...

  7. luogu P5294 [HNOI2019]序列

    传送门 这个什么鬼证明直接看uoj的题解吧根本不会证明 首先方案一定是若干段等值的\(B\),然后对于一段,\(B\)的值应该是\(A\)的平均值.这个最优方案是可以线性构造的,也就是维护以区间平均值 ...

  8. 题解 luogu P1144 【最短路计数】

    本蒟蒻也来发一次题解第一篇请见谅 这个题有几个要点 1.无向无权图,建图的时候别忘记建来回的有向边[因此WA掉1次 2.无权嘛,那么边长建成1就好了2333333 3.最短路采用迪杰斯特拉(别忘用堆优 ...

  9. 【洛谷5288】[HNOI2019] 多边形(二叉树模型)

    点此看题面 大致题意: 给你一个多边形,用若干不重合.不相交的线段将其划分为若干三角形区域,并定义旋转操作\((a,c)\)为选定\(4\)个点\(a,b,c,d\)满足\(a<b<c&l ...

随机推荐

  1. SQL进阶-隐式类型转换

    一.隐式类型转换 1.隐式类型转换 隐式类型转换: '; 程序可读性差,且依赖数据库的隐式转换规则,如果数据库升级,则程序可能无法正确执行: 有可能会导致索引失效: 有可能会导致意想不到的结果: 显式 ...

  2. VTK图像遮罩(vtkImageMask)

    #!/usr/bin/env python import vtk reader = vtk.vtkJPEGReader() reader.SetFileName("Pygoscelis ad ...

  3. nginx 反向代理配置示例

    Nginx反向代理在生产环境中使用很多的. 场景1: 域名没有备案,可以把域名解析到香港一台云主机上,在香港云主机做个代理,而网站数据是在大陆的服务器上. server { listen ; serv ...

  4. Spring通知,顾问,增强

    1.AOP  (Aspect  Oriented Programming  面向切面编程) 在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编 ...

  5. putty WinScp 免密登录远程 Linux

    该方法的原理是预先生成一对公钥和私钥,私钥以文件的形式保存在本地,公钥保存在远程机器上.这样每次登录只需指定私钥文件,远程机器通过比对公钥和私钥来验证登录的合法性. Putty 免密登录 第一步 生成 ...

  6. 一种Winform类electron的实现

    最近看了一篇文章  Winform客户端内嵌Vue页面  使用html作为winform的界面(其实这种做法早在MFC时代就已经有了),不过感觉文章中的封装并不够彻底,所以我忍不住要发一篇博客来说说我 ...

  7. Linux中git用https连接时不用每次输入密码

    应用场景: 比如每天凌晨执行crontab对应的项目部署脚本(使用git作为项目的版本控制). 如果不这样做会怎么样? 每次部署都要git clone并输入对应的用户名和密码,需要人工.这样就显得很不 ...

  8. FZU Monthly-201909 tutorial

    FZU Monthly-201909 tutorial 题目(难度递增) easy easy-medium medium medium-hard hard 思维难度 AB CD EF G H A. I ...

  9. ModuleNotFoundError: No module named 'pymysql'

    出现此提示表示系统中没有安装PyMySQL,可以通过pip PyMySQL进行安装. 安装之后,执行import pymysql仍然不可用! why? 检查后发现系统中存在python2与python ...

  10. Python3基础 from...import 局部导入

             Python : 3.7.3          OS : Ubuntu 18.04.2 LTS         IDE : pycharm-community-2019.1.3    ...