[计蒜之道2019 复赛 A]外教 Michale 变身大熊猫

Online Judge2019计蒜之道 复赛 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 变身大熊猫的更多相关文章

  1. 2018 计蒜之道复赛 贝壳找房魔法师顾问(并查集+dfs判环)

    贝壳找房在遥远的传奇境外,找到了一个强大的魔法师顾问.他有 22 串数量相同的法力水晶,每个法力水晶可能有不同的颜色.为了方便起见,可以将每串法力水晶视为一个长度不大于 10^5105,字符集不大于  ...

  2. 计蒜之道 百度AI小课堂-上升子序列

    计蒜之道 百度AI小课堂-上升子序列 题目描述 给一个长度为 \(n\) 的数组 \(a\) .试将其划分为两个严格上升子序列,并使其长度差最小. 输入格式 输入包含多组数据. 数据的第一行为一个正整 ...

  3. 2019 计蒜之道 复赛 E. 撑起信息安全“保护伞” (贪心,构造,规律)

    为了给全球小学员打起信息安全"保护伞",VIPKID 还建立了一套立体化的安全防御体系,7 \times 247×24 小时持续安全监控与应急响应等多项联动,具备业界最高级别的数据 ...

  4. 2019 计蒜之道 复赛 B. 个性化评测系统 (模拟,实现,暴搜)

    24.02% 1000ms 262144K "因材施教"的教育方式自古有之,互联网时代,要实现真正意义上的个性化教育,离不开大数据技术的扶持.VIPKID 英语 2020 多万学员 ...

  5. 2019 计蒜之道 复赛 D. “星云系统”(单调栈)

    VIPKID 是在线少儿英语教育平台,网络稳定是在线教育课程质量的红线,VIPKID 为此推出了全球最稳定的教育网络系统 -- "星云系统".星云系统目前建立了覆盖全球 3535 ...

  6. 2016计蒜之道复赛 百度地图的实时路况 floyd+cdq分治

    链接:https://nanti.jisuanke.com/t/11217 奉上官方题解: 枚举 d(x , y , z) 中的 y,把 y 从这个图中删去,再求这时的全源最短路即可,使用 Floyd ...

  7. 2016计蒜之道复赛 菜鸟物流的运输网络 网络流EK

    题源:https://nanti.jisuanke.com/t/11215 分析:这题是一个比较经典的网络流模型.把中间节点当做源,两端节点当做汇,对节点进行拆点,做一个流量为 22 的流即可. 吐槽 ...

  8. 2016计蒜之道复赛B题:联想专卖店促销

    题解 思路: 二分答案,设我们要check的值为x. 注意到每一个礼包都有,一个U盘,一个鼠标. 剩余的,分别为一个机械键盘,一个U盘,一个鼠标. 当礼包数目为x时,我们至多可以提供a-x个普通,b- ...

  9. 2016计蒜之道复赛 百度地图的实时路况(Floyd 分治)

    题意 题目链接 Sol 首先一个结论:floyd算法的正确性与最外层\(k\)的顺序无关(只要保证是排列即可) 我大概想到一种证明方式就是把最短路树上的链拿出来,不论怎样枚举都会合并其中的两段,所以正 ...

随机推荐

  1. 【BZOJ2298】【luoguP2519】problem a

    description 一次考试共有n个人参加,第i个人说:"有ai个人分数比我高,bi个人分数比我低."问最少有几个人没有说真话(可能有相同的分数) analysis 这题转化模 ...

  2. 0908CSP-S模拟测试赛后总结

    我早就料到昨天会考两场2333 话说老师终于给模拟赛改名了啊. 距离NOIP祭日还有60天hhh. 以上是废话. %%%DeepinC无敌神 -rank1 zkt神.kx神.动动神 -rank2 有钱 ...

  3. linux下常见的包安装方式

    linux下常见的包安装方式 一.总结 一句话总结: rpm包安装 tar.gz源代码包安装 yum方式安装rpm包 bin文件安装 1.yum是什么? 安装所有依赖的软件包 Yum(全称为 Yell ...

  4. Activity详解一 配置、启动和关闭activity转载 https://www.cnblogs.com/androidWuYou/p/5887726.html

    先看效果图: Android为我们提供了四种应组件,分别为Activity.Service.Broadcast receivers和Content providers,这些组建也就是我们开发一个And ...

  5. 获取一个数组(vector)与查找值(value)的差最小绝对值的成员索引的算法

    代码如下: 函数作用:传递进来一个数组(vector),和一个需要查找的值(value),返回与value的差值绝对值最小的vector成员索引,若value不在vector范围中,则返回-1: in ...

  6. Mysql优化系列之索引性能

    实际上,前面的数据类型和表结构设计优化不能算优化,只能算规范,也就是说在设计表的时候,应该且必须做到这些 索引是sql优化的核心部分,在<高性能Mysql>中单独抽出一章讲,也印证了其重要 ...

  7. PKU Campus 2015

    PKU Campus 2015 B 注意到竖着落下不改变列模 4 的结果.问题转化为:模 4 系下,给序列,可选长度为 4 子区间,区间加一,能否让所有元素相等. C.Rabbit's Festiva ...

  8. HYNB Round 15: PKU Campus 2019

    HYNB Round 15: PKU Campus 2019 C. Parade 题意 将平面上n*2个点安排在长度为n的两行上. 做法 首先可以忽略每个点之间的影响,只用考虑匹配即可 然后把所以点归 ...

  9. node web项目结构

  10. css---3链接伪类与动态伪类

    链接伪类link:表示作为超链接,并指向一个未访问的地址的所有锚 链接伪类不可以加在div上 <!DOCTYPE html> <html> <head> <m ...