[计蒜之道2019 复赛 A]外教 Michale 变身大熊猫
[计蒜之道2019 复赛 A]外教 Michale 变身大熊猫
Online Judge:2019计蒜之道 复赛 A
Label:LIS+线段树、树状数组+快速幂(模逆元)
题目描述

题解:
pre.关于本题中模逆元的提示:
对于一个质数mod,q的模逆元是\(q^{mod-2}\)。也就是说对于本题,平时一般用形如\(G=\frac{p}{q}\)的分式表示概率,现在,我们利用模逆元来表示这个概率,即\(G=p*q^{mod-2}\)。
那这道题里\(mod=998244353\)是个质数,那就可以利用上面的提示\(G=p*q^{mod-2}\),很明显要用到快速幂,而这个\(q\)就是LIS的个数,那我们只要求每个位置对应的p即可。
①.70%数据的\(O(N^2)\)做法:
想到LIS的O(NlogN)做法——用树状数组或线段树维护前缀最小值优化一下dp。然后可以求出最大上升子序列的长度mal ,接着分别从左到右,再从右到左求一下每个点会在几条LIS上,然后左右的方案数乘一下就是p了。预处理很明显要先离散化一下。离线赛时的70分代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
typedef long long ll;
const int N=1e5+10;
const int mod=998244353;
int r[N],l[N];
int qsm(int x,int b){
int res=1;
while(b){
if(b&1)res=1LL*res*x%mod;
x=1LL*x*x%mod;
b>>=1;
}
return res;
}
int B[N];
int n,num,a[N],b[N],dp[N];
int lowbit(int x){return x&-x;}
void update(int x,int d){
while(x<=num)B[x]=max(B[x],d),x+=lowbit(x);
}
int query(int x){
int res=0;
while(x)res=max(res,B[x]),x-=lowbit(x);
return res;
}
int cnt[N],all;
signed main(){
// freopen("lis.in","r",stdin),freopen("lis.out","w",stdout);
scanf("%lld",&n);
for(int i=1;i<=n;i++)scanf("%lld",&a[i]),b[i]=a[i];
sort(b+1,b+n+1);
num=unique(b+1,b+n+1)-b-1;
for(int i=1;i<=n;i++)a[i]=lower_bound(b+1,b+num+1,a[i])-b;
int mal=0;
for(int i=1;i<=n;i++){
int now=query(a[i]-1);
dp[i]=now+1;
if(dp[i]>mal)mal=dp[i];
update(a[i],dp[i]);
}
a[0]=0,dp[0]=0,l[0]=1;
a[n+1]=num+1,dp[n+1]=mal+1,r[n+1]=1;n++;
for(int i=0;i<=n;i++){
for(int j=i+1;j<=n;j++){
if((dp[j]!=dp[i]+1)||a[j]<=a[i])continue;
l[j]=(l[j]+l[i])%mod;
}
}
for(int i=n;i>=0;i--){
for(int j=i-1;j>=0;j--){
if((dp[j]!=dp[i]-1)||a[j]>=a[i])continue;
r[j]=(r[j]+r[i])%mod;
}
}
int all=l[0]*r[0]%mod,q=qsm(all,mod-2);
for(int i=1;i<n;i++)printf("%lld ",r[i]*l[i]%mod*q%mod);
}
②.\(O(NlogN)\)正解
上面的代码也可以优化,但是我们可以直接在求LIS时候维护方案数。
也是一样的思路,从左到右扫一遍,再从右到左扫一遍,然后乘一下得到方案数。然后下面代码利用树状数组维护到目前为止,以离散化后的数字i结尾的LIS最长为\(c[i]\),以及,以其结尾的LIS这么长有\(ti[i]\)条。
由于一次从左到右,一次从右到左,所以打两组树状数组。大致思路同上面的代码:
//快速幂->模逆元,树状数组、线段树维护
#include<bits/stdc++.h>
using namespace std;
#define int long long
typedef long long ll;
const int N=1e5+10;
const int mod=998244353;
int num,a[N],b[N];
int dp[N],li[N],ans[N];
int presum,c[N],ti[N];
int add1(int x,int mal,int d){
while(x<=num){
if(mal>c[x])c[x]=mal,ti[x]=d;
else if(mal==c[x])ti[x]=(ti[x]+d)%mod;
x+=x&(-x);
}
}
int sum1(int x){
int res=0;
while(x){
if(res<c[x])res=c[x],presum=ti[x];
else if(res==c[x])presum+=ti[x];
x-=x&(-x);
}
return res;
}
void add2(int x,int mal,int d){
while(x){
if(mal>c[x])c[x]=mal,ti[x]=d;
else if(mal==c[x])ti[x]=(ti[x]+d)%mod;
x-=x&(-x);
}
}
int sum2(int x){
int res=0;
while(x<=num){
if(res<c[x])res=c[x],presum=ti[x];
else if(res==c[x])presum+=ti[x];
x+=x&(-x);
}
return res;
}
int ksm(int x,int b){
int res=1;
while(b){
if(b&1)res=res*x%mod;
x=x*x%mod;
b>>=1;
}
return res;
}
signed main(){
int n;scanf("%lld",&n);
for(int i=1;i<=n;i++)scanf("%lld",&a[i]),b[i]=a[i];
sort(b+1,b+n+1);
num=unique(b+1,b+n+1)-b-1;
for(int i=1;i<=n;i++)a[i]=lower_bound(b+1,b+num+1,a[i])-b;
int lis=0;
for(int i=1;i<=n;i++){
presum=0;
int now=sum1(a[i]-1);presum%=mod;
dp[i]=now+1;
lis=max(lis,dp[i]);
if(dp[i]==1)li[i]=1;
else li[i]=presum;
add1(a[i],dp[i],li[i]);
}
memset(c,0,sizeof(c));
memset(ti,0,sizeof(ti));
int tot=0;
for(int i=n;i>=1;i--){
presum=0;
int now=sum2(a[i]+1);presum%=mod;
int ri=(now==0?1:presum);
if((dp[i]+now)==lis)ans[i]=li[i]*ri%mod;
if(dp[i]==lis)tot=(tot+ans[i])%mod;
add2(a[i],now+1,ri);
}
int q=ksm(tot,mod-2);
for(int i=1;i<=n;i++)printf("%lld ",ans[i]*q%mod);
return 0;
}
[计蒜之道2019 复赛 A]外教 Michale 变身大熊猫的更多相关文章
- 2018 计蒜之道复赛 贝壳找房魔法师顾问(并查集+dfs判环)
贝壳找房在遥远的传奇境外,找到了一个强大的魔法师顾问.他有 22 串数量相同的法力水晶,每个法力水晶可能有不同的颜色.为了方便起见,可以将每串法力水晶视为一个长度不大于 10^5105,字符集不大于 ...
- 计蒜之道 百度AI小课堂-上升子序列
计蒜之道 百度AI小课堂-上升子序列 题目描述 给一个长度为 \(n\) 的数组 \(a\) .试将其划分为两个严格上升子序列,并使其长度差最小. 输入格式 输入包含多组数据. 数据的第一行为一个正整 ...
- 2019 计蒜之道 复赛 E. 撑起信息安全“保护伞” (贪心,构造,规律)
为了给全球小学员打起信息安全"保护伞",VIPKID 还建立了一套立体化的安全防御体系,7 \times 247×24 小时持续安全监控与应急响应等多项联动,具备业界最高级别的数据 ...
- 2019 计蒜之道 复赛 B. 个性化评测系统 (模拟,实现,暴搜)
24.02% 1000ms 262144K "因材施教"的教育方式自古有之,互联网时代,要实现真正意义上的个性化教育,离不开大数据技术的扶持.VIPKID 英语 2020 多万学员 ...
- 2019 计蒜之道 复赛 D. “星云系统”(单调栈)
VIPKID 是在线少儿英语教育平台,网络稳定是在线教育课程质量的红线,VIPKID 为此推出了全球最稳定的教育网络系统 -- "星云系统".星云系统目前建立了覆盖全球 3535 ...
- 2016计蒜之道复赛 百度地图的实时路况 floyd+cdq分治
链接:https://nanti.jisuanke.com/t/11217 奉上官方题解: 枚举 d(x , y , z) 中的 y,把 y 从这个图中删去,再求这时的全源最短路即可,使用 Floyd ...
- 2016计蒜之道复赛 菜鸟物流的运输网络 网络流EK
题源:https://nanti.jisuanke.com/t/11215 分析:这题是一个比较经典的网络流模型.把中间节点当做源,两端节点当做汇,对节点进行拆点,做一个流量为 22 的流即可. 吐槽 ...
- 2016计蒜之道复赛B题:联想专卖店促销
题解 思路: 二分答案,设我们要check的值为x. 注意到每一个礼包都有,一个U盘,一个鼠标. 剩余的,分别为一个机械键盘,一个U盘,一个鼠标. 当礼包数目为x时,我们至多可以提供a-x个普通,b- ...
- 2016计蒜之道复赛 百度地图的实时路况(Floyd 分治)
题意 题目链接 Sol 首先一个结论:floyd算法的正确性与最外层\(k\)的顺序无关(只要保证是排列即可) 我大概想到一种证明方式就是把最短路树上的链拿出来,不论怎样枚举都会合并其中的两段,所以正 ...
随机推荐
- Delphi 实现窗体无标题栏有边框
1.在窗体的public区写下这一句: Procedure CreateParams(var Params :TCreateParams);override;2然后把光标停在这一行上,按下Ctrl+S ...
- 移动端click点透bug
移动端click点透bug click点透bug有一个特定的产生情况: 当上层元素是tap事件,且tap后消失,下层元素是click事件.这个时候,tap上层元素的时候就会触发下层元素的click事件 ...
- timestamp的自动更新 ON UPDATE CURRENT_TIMESTAMP
最近有一个关于MySQL版本升级的事,涉及到一些关于时间类型的细节问题需要查明,因此到官网找到相关文章,翻出来比较方便自己理解,博客这里也贴一下. 参考官网网址: https://dev.mysql. ...
- Matlab神经网络验证码识别
本文,将会简述如何利用Matlab的强大功能,调用神经网络处理验证码的识别问题. 预备知识,Matlab基础编程,神经网络基础. 可以先看下: Matlab基础视频教程 Matlab经典教程--从 ...
- golang 获取当前可执行程序的当前路径
import ( "errors" // "fmt" "os" "os/exec" "path/filepat ...
- 用shell编写小九九乘法表程序
1.使用for循环 运行结果: 2.方法二:for循环 运行结果: 备注: 1. echo -n 的意思是不自动换行,因为在linux shell中 echo到最后一个字符时会自动换行的,所以echo ...
- csps模拟测试707172部分题解myc
题面:https://www.cnblogs.com/Juve/articles/11678524.html 骆驼:构造题,留坑 根据5×5的矩形构造成大矩形 毛一琛: mid in the midd ...
- session过期跳转到登陆页面并跳出iframe框架的两个方法
最近在做拦截器,判断用户登录后操作超时,失去权限然后要重新登录,但是用的iframe,返回的登陆页总是在框架中显示,我百度了下,总是只有其中一个方法,现在分享下两种解决方法,希望对你们有帮助: 方法一 ...
- fiddler报错:creation of the root certificate was not successful 证书安装不成功
fiddler提示:creation of the root certificate was not successful 证书安装不成功 首先 找到Tools——>Options 在弹出的菜单 ...
- vue 单纯的获取经纬度 百度与高德 H5
首先用百度的api举个例子 首先在index页面引入如下: <script type="text/javascript" src="http://api.map.b ...