原题传送门

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. 机器学习之决策树原理和sklearn实践

    1. 场景描述 时间:早上八点,地点:婚介所 '闺女,我有给你找了个合适的对象,今天要不要见一面?' '多大?' '26岁' '长的帅吗?' '还可以,不算太帅' '工资高吗?' '略高于平均水平' ...

  2. Hash总结

    算法介绍 这个没什么好说的,就是一段比较简单的代码,具体的话要看题目. 自然溢出 这个是比较好用而且容易被卡的一种Hash方式. 用\(2^{64}\)当模数然后做\(Hash\),常数比较小. 单模 ...

  3. 组合模式( Composite Pattern)

    参考文档:http://blog.csdn.net/ai92/article/details/298336 定义: 组合多个对象形成树形结构以表示“整体-部分”的结构层次. 设计动机: 这幅图片我们都 ...

  4. 解决'maven lifecycle mapping not converted'的问题

    基于maven的项目,使用各种maven plugin来完成开发中的各种工作,例如编译代码,打包,部署等等… 每个plugin包含许多的goal,用来做特定的事情.典型的基于java的maven项目就 ...

  5. 主题模型TopicModel:主题模型LDA的应用

    http://blog.csdn.net/pipisorry/article/details/45665779 主题模型LDA的应用 拿到这些topic后继续后面的这些应用怎么做呢:除了推断出这些主题 ...

  6. SpringMVC(十六):如何使用编程方式替代/WEB-INF/web.xml中的配置信息

    在构建springmvc+mybatis项目时,更常用的方式是采用web.xml来配置,而且一般情况下会在web.xml中使用ContextLoaderListener加载applicationCon ...

  7. 搭建基于 Anaconda 管理的多用户 JupyterHub 平台

    搭建基于 Anaconda 管理的多用户 JupyterHub 平台 情况:计算工作站放在实验室,多个同学需要接入使用,且需要各自独立的环境,并使用 Jupyter notebook 平台以方便协作. ...

  8. ROC曲线 VS PR曲线

    python机器学习-乳腺癌细胞挖掘(博主亲自录制视频)https://study.163.com/course/introduction.htm?courseId=1005269003&ut ...

  9. ES6 - 解构(数组和对象)

    解构对象 /** * 解构:快捷,方便 * * 对象解构 */ { var expense = { type: "es6", amount: "45" }; / ...

  10. kubernetes篇 容器用户权限控制

    问题起源 问题起源于一个开发BUG:正常运行一段时间的POD,突然有一天运行报错了,错误是没有操作目录的权限,查其原因,原来是镜像被更新了,镜像添加了操作用户,而被操作的目录(NFS目录)并不具备普通 ...