外教变身萌翻小学员,VIPKID “AR 变脸” 打造趣味互动课堂,这是在线少儿英语品牌 VIPKID 全新推出的辅助教学功能——AR 变脸,外教在上课过程中可以随意选取合适的表情贴纸。人脸识别和表情识别等技术的应用帮助“AR 变脸”这一教辅功能更好地服务外教,更好地激励学生积极地参与课堂内容,提升在线课堂的趣味性。

现在,外教 Michale 就变身了一只萌萌的大熊猫,给你出来了一道关于数列的题目,请看题:

给定长度为 nn 的数列 aa,显然这个数列有很多最长上升子序列,我们等概率地取出一个最长上升子序列,求每个数被选中的概率,对 998244353998244353 取模。

提示:

如果你知道如何表示一个分数在模意义下的值可以直接做题了

对于一个分数 \frac{p}{q}qp​,我们用模意义下的整数 p\times q^{-1}p×q−1 表示 \frac{p}{q}qp​在模意义下的值。

其中 q^{-1}q−1 表示 qq 在模意义下的逆元,满足 q \times q^{-1}q×q−1 在模意义下等于 11。

对于模数 modmod,且 modmod 为质数时,qq 的逆元等于q^{mod-2}qmod−2

输入格式

第一行输入一个整数 nn 表示数列 aa 的长度。

接下来一行输入 nn 个整数 a_iai​。

输出格式

输出 nn 个整数,表示每个数字被选中的概率。

数据规模

a_i \le 10^9,n \le 5 \times 10^5ai​≤109,n≤5×105

输出时每行末尾的多余空格,不影响答案正确性

样例输入复制

4
1 2 2 4

样例输出复制

1 499122177 499122177 1

分析:

题解出来基本就知道该怎么写了。

#include<bits/stdc++.h>
#define ls rt<<1
#define rs rt<<1|1#define mod 998244353
#define N 4000005
using namespace std;
typedef long long LL;
LL max_len[N], max_num[N], f[N], ff[N], a[N], b[N], g[N], gg[N], n;
//设f[i]为以i结尾的最长上升子序列长度,ff[i]为以i结尾的最长上升子序列的个数,g[i]与gg[i]是反过来求最长下降子序列同理
//max_len表示最长上升子序列的长度(最大值)  max_num表示最长上升子序列个数(最大值的个数)
void pushup(int rt)
{if(max_len[ls] > max_len[rs])max_len[rt] = max_len[ls], max_num[rt] = max_num[ls];if(max_len[ls] < max_len[rs])max_len[rt] = max_len[rs], max_num[rt] = max_num[rs];if(max_len[ls] == max_len[rs])max_len[rt] = max_len[ls], max_num[rt] = max_num[ls] + max_num[rs];max_num[rt] %= mod;
}
void build(int l, int r, int rt)
{if(l == r)return;max_len[rt] = max_num[rt] = 0;int mid = (l + r) >> 1;build(l, mid, ls);build(mid + 1, r, rs);pushup(rt);
}
//更新x位置贡献,
void update(int l, int r, int x, LL nowlen, LL nownum, int rt)
{if(l == r){if(max_len[rt] == nowlen)max_num[rt] += nownum;elsemax_num[rt] = nownum;max_num[rt] %= mod;max_len[rt] = nowlen;return;}int mid = (l + r) >> 1;if(x <= mid)update(l, mid, x, nowlen, nownum, ls);elseupdate(mid + 1, r, x, nowlen, nownum, rs);pushup(rt);
}
int query1(int l, int r, int L, int R, int rt) //求最大长度值
{if(L <= l && r <= R)return max_len[rt];int mid = (l + r) >> 1, ret = 0;if(L <= mid)ret = query1(l, mid, L, R, ls);if(R > mid)ret = max(ret, query1(mid + 1, r, L, R, rs));return ret;
}
//求最大值的个数且保证最大上升子序列长度等于nowlen
int query2(int l, int r, int L, int R, int rt, LL nowlen)
{if(L <= l && r <= R){if(max_len[rt] == nowlen)return max_num[rt];//注意要等于最大值才能返回return 0;}int mid = (l + r) >> 1, ret = 0;if(L <= mid)ret = query2(l, mid, L, R, ls, nowlen);if(R > mid)ret += query2(mid + 1, r, L, R, rs, nowlen), ret %= mod;return ret;
}
LL qpow(LL y, LL x) //快速幂
{LL t = y, ans = 1;for(; x; x >>= 1, t = t * t % mod)if(x & 1)ans = ans * t % mod;return ans;
}
signed main()
{scanf("%lld", &n);for(int i = 1; i <= n; i ++)scanf("%lld", &a[i]), b[i] = a[i];sort(b + 1, b + 1 + n);int len=unique(b+1,b+1+n)-(b+1);for(int i = 1; i <= n; i ++)a[i] = lower_bound(b + 1, b + 1 + len, a[i]) - b; //离散化build(0, n, 1);//0是下界,为了1好办for(int i = 1; i <= n; i ++){f[i] = query1(0, n, 0, a[i] - 1, 1) + 1;//求小于a[i]当中f值最大的数 + 1就是以i结尾的最长上升子序列ff[i] = query2(0, n, 0, a[i] - 1, 1, f[i] - 1);//同上,最大值的个数就是以i结尾的最长上升子序列的个数ff[i] = max(ff[i], 1LL);//注意长度和个数至少为1update(0, n, a[i], f[i], ff[i], 1);//插入}int qq = qpow(max_num[1], mod - 2), pp = max_len[1];memset(max_len, 0, sizeof(max_len));memset(max_num, 0, sizeof(max_num));build(1, n + 1, 1);for(int i = n; i >= 1; i --){g[i] = query1(1, n + 1, a[i] + 1, n + 1, 1) + 1;//同上注意边界gg[i] = query2(1, n + 1, a[i] + 1, n + 1, 1, g[i] - 1);gg[i] = max(gg[i], 1LL);update(1, n + 1, a[i], g[i], gg[i], 1);}for(int i = 1; i <= n; i ++){if(f[i] + g[i] - 1 == pp)printf("%lld ", ff[i] * gg[i] % mod * qq % mod);elseprintf("0 ");}return 0;
}

[计蒜之道2019 复赛 A]外教 Michale 变身大熊猫 (线段树求LIS+思维)相关推荐

  1. 计蒜之道2019 复赛 A.外教 Michale 变身大熊猫 线段树辅助建分层图dp

    题意:给出一个序列,随机取出其中一条最长上升子序列,问你取到每个数的概率是多少. 说起概率,我们可以尝试去求最长上升子序列的个数,显然每个点被取到的概率是 含有这个点的最长上升子序列个数/总共最长上升 ...

  2. 2019计蒜之道复赛A:外教Michale变身大熊猫【树状数组+dp】

    题目: 题目在这里~~~ 分析: 按照题意,只需要找到最长上升子序列的数量和每个数对最长上升子序列的贡献次数即可,可以二分找到经过每个数的最长上升子序列的长度,但这样不好统计数量:考虑dp,定义dp[ ...

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

    题目链接 题意:本题就是很显然的题意,让你求出共有多少个最长上升子序列,每个数在多少个最长上升子序列中. 这题的难点在于如何求出每个数在多少最长上升子序列中,显然可以用dp,直接dp时间复杂度不允许, ...

  4. 计蒜之道2019 复赛 D-星云系统(单调栈)

    原题链接: https://nanti.jisuanke.com/t/39614 题意: 给出一个长度为n的字符串,找出其中长度为k的字典序最小的子序列. 题解: 设串长为n,则只需删掉 n-k个字符 ...

  5. 2019计蒜之道复赛-A-外教 Michale 变身大熊猫(线段树求LIS及其元素出现概率)

    时限:1000ms            空间限制:524288K 题目链接https://nanti.jisuanke.com/t/39611 外教变身萌翻小学员,VIPKID "AR 变 ...

  6. The Preliminary Contest for ICPC Asia Shanghai 2019 B. Light bulbs(卡了线段树空间的思维题)

    传送门:https://nanti.jisuanke.com/t/41399 题目描述 There are NNN light bulbs indexed from 000 to N−1N−1N−1. ...

  7. 2016计蒜之道复赛 微信钱包付款

    2016计蒜之道复赛  微信钱包付款 一.题意: 微信钱包付款 给定n(0≤n≤10​10000),求a,,b,c使得a+b+c=n,并且f(a)=f(b)=f(c),f(n)定义为n的各数位的和,例 ...

  8. 计蒜之道2015程序设计大赛初赛第三场——腾讯手机地图

    计蒜之道2015程序设计大赛初赛第三场--腾讯手机地图 (一)题面 腾讯手机地图的定位功能用到了用户手机的多种信号,这其中有的信号的作用范围近,有的信号作用的范围则远一些.有的信号相对于用户在不同的方 ...

  9. 2017 计蒜之道 初赛 第一场 A题B题

    阿里九游开放平台近日上架了一款新的益智类游戏--成三棋.成三棋是我国非常古老的一个双人棋类游戏,其棋盘如下图所示: 成三棋的棋盘上有很多条线段,只能在线段交叉点上放入棋子.我们可以用坐标系来描述棋盘: ...

最新文章

  1. 网页挂马防护市场探索
  2. MyEclipse 2013 新功能介绍
  3. improve怎么加ing_英语当中的ing
  4. epub java虚拟机精讲_高级 Java 必须掌握:JVM 分析工具和查看命令,超详细!
  5. cvs svnmanager
  6. php 文件写入磁盘错误,Linux磁盘读写故障的通常处理流程
  7. 【287】◀▶ arcpy 常用类说明
  8. mui switch 实现方案 让你的html 设计更贴近原生
  9. Python读写Excel文件中指定区域单元格内容
  10. java Queue
  11. 铃木雅臣晶体管电路设计学习笔记1
  12. 抖音短视频去水印网站 视频消重防删免费
  13. 程序员懒人投资大法之定投指数基金
  14. BigDecimal.ROUND_HALF_EVEN (银行家算法)
  15. 盘点无线互联网战国七雄
  16. 网络文件共享服务主流----FTP文件传输协议
  17. 钉钉发起审批流程分析
  18. “挖矿2.0”:资本方不是只能割区块链的韭菜
  19. 利用MATLAB仿真实现交通红绿灯识别的目的
  20. python--自动创建文件和创建目录的方法

热门文章

  1. oracle通过表空间文件进行数据库恢复,Oracle数据库表空间恢复方案_oracle
  2. 高校大数据实验室建设方案包括哪些?
  3. 2021年安全员-C证(陕西省)及安全员-C证(陕西省)证考试
  4. 无经验测试找工作,简历怎么写比较好?1000个已成功入职的软件测试工程师的建议...
  5. 多条件查询日志linux,linux 多文件多条件查看日志命令
  6. (续)Visual Studio 连接SQL Server数据库,代码连接
  7. java传值给js 换行_JavaScript用document.write()输出换行的示例代码
  8. 搭建 SVN Linux服务器
  9. selenium 成功绕过淘宝登录反爬机制(headless模式)
  10. 生存分析/Weibull Distribution韦布尔分布