原题传送门

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. MySQL避免插入重复记录:唯一性约束

      mysql在存在主键冲突或者唯一键冲突的情况下,根据插入策略不同,一般有以下三种避免方法.1.insert ignore2.replace into3.insert on duplicate ke ...

  2. linux 搭建局域网YUM源仓库服务器

    yum简介 Yum(全称为 Yellow dog Updater, Modified)是一个在Fedora和RedHat以及CentOS中的Shell前端软件包管理器.基于RPM包管理,能够从指定的服 ...

  3. 上传一句话木马时<? php被过滤的解决办法

    i春秋“百度杯”CTF比赛 九月场 web题 upload 题目描述:想怎么传就怎么传,就是这么任性.tips:flag在flag.php中 打开题目发现 于是想到通过上传一句话木马进入后台 上传一句 ...

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

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

  5. Canal - 数据同步 - 阿里巴巴 MySQL binlog 增量订阅&消费组件

    背景 早期,阿里巴巴 B2B 公司因为存在杭州和美国双机房部署,存在跨机房同步的业务需求 ,主要是基于trigger的方式获取增量变更.从 2010 年开始,公司开始逐步尝试数据库日志解析,获取增量变 ...

  6. linux查看实时日志命令

    tail -f localhost_access_log.2018-12-11.txt(当前时间)今天的实时日志,操作一下系统,就会报出相应的日志

  7. 两分钟观看 nodejs、 iojs、 npmjs 之间的狗血剧情

    开门大吉,欢迎光临.这是 乐玩nodejs npm工具库 微信公众号的第一篇文章,那就先来说说 nodejs/npm 的小秘密,话不多说,赶快开始: 通过一个时间线简要描述下 2008 年 V8 引擎 ...

  8. ShenZhenXiaoLengHuanYou Technology Co.,Ltd 技术支持网站

    本网页为ShenZhenXiaoLengHuanYou Technology Co.,Ltd 团队的技术支持网址,如果在我们开发的游戏中遇到任何问题,欢迎联系我们! QQ:2535510006 邮箱: ...

  9. 一次升级jar包遇到的空指针异常

    今天自己在升级公司的一个jar后,一直报空指针异常.代码如下 package com.zhuanche.http; import com.alibaba.fastjson.JSON; import c ...

  10. Ubuntu tricks

    linux 复制文件夹内所有文件到另一个文件夹 cp -Rf /home/user1/* /root/temp/ 将 /home/user1目录下的所有东西拷到/root/temp/下而不拷贝user ...