EVERYTHING HAPPENS FOR THE BEST|

wnsyou

园龄:2年4个月粉丝:19关注:16

2024-08-03 15:33阅读: 47评论: 0推荐: 0

CF1946F Nobody is needed 题解

Nobody is needed

推销我的洛谷博客。

题意

多组数据。

给定一个长度为 n排列 a,你需要回答 q 组询问,每组询问给出 l,r,求有多少个子序列 t 使得:

  • lt1<t2<<tkr
  • ati|ati+1(1i<k)

数据范围

  • 1n,q106
  • a一个排列
  • 1n,q106

思路

考虑使用 dp,令 dpi 表示以 ai 结尾的合法子序列个数,拓扑序为 i 从小到大。

那么转移呢,很显然若是写收集形则 dpi 可以从所有 ai 的约数处转移过来,总复杂度是 O(1ini) 的,可以用代码计算一下,当 n=106 时,总共需要大约 6×108,不太能接受。

若是写扩散形,又不便于确定对于每组询问的答案。

可以考虑将拓扑序转为 i 从大到小,那么对于 i,会发生修改的 dpj 只有那些 ijai|aj,也就是说只有 nai 处的 dp 需要修改,总复杂度为 O(1inni),很典型的调和级数 O(nlogn),可以接受。

那么考虑怎么更新 dp 数组,正如上文所说,每次发生修改的只有 ai 的倍数,而修改的贡献可以分为 aiai×x(x2) 的贡献和 ai×x(x2)ai×x×y(x,y2) 的贡献,但如果 ai 所对应的下标(即 i)在 ai×x 的下标后面,则无法产生贡献,ai×xai×x×y 同理。

为了保证查询时答案没有超出 [l,r] 的范围,需要在每次更新完 dp 数组后处理那些 l=i 的查询,答案就是 ijrdpj,为了快速求出答案,使用树状数组维护 dp 数组的和。

详细见代码。

复杂度

  • 时间:O(qlogn+nlog2n)
  • 空间:O(n+q)

Code

点击查看代码
#include <iostream>
#include <vector>
#define _1 (__int128)1
using namespace std;
using ll = long long;
const int N = 1e6 + 10;
inline int lowbit (int x) {
return x & -x;
}
int T, n, q, a[N], b[N];
ll ans[N], tr[N], dp[N];
vector<pair<int, int>> qry[N];
void modify (int x, int y) {
for (int i = x; i <= n; i += lowbit(i)) tr[i] += y;
}
ll Query (int x) {
ll ret = 0;
for (int i = x; i; i -= lowbit(i)) ret += tr[i];
return ret;
}
void Solve () {
cin >> n >> q;
for (int i = 1; i <= n; i++)
cin >> a[i], b[a[i]] = i, tr[i] = 0, qry[i] = vector<pair<int, int>> (); // 多测要清空,b[i] 用于记录 i 在 a 中对应的下标
for (int i = 1, l, r; i <= q; i++)
cin >> l >> r, qry[l].push_back({r, i}); // 离线处理询问
for (int i = n; i; i--) {
dp[a[i]] = 1; // 初始状态
for (int j = a[i]; j <= n; j += a[i])
if (b[j] >= b[a[i]]) // 将两种转移合并可以这样写
for (int k = j * 2; k <= n; k += j) // 注意是 k += j 而不是 k += a[i]
if (b[k] > b[j])
dp[k] += dp[j];
for (int j = a[i]; j <= n; j += a[i])
modify(b[j], dp[j]), dp[j] = 0; // 用树状数组维护 dp 和,dp 要清空
for (auto [j, id] : qry[i])
ans[id] = Query(j) - Query(i - 1); // 差分处理答案
}
for (int i = 1; i <= q; i++)
cout << ans[i] << ' ';
}
int main () {
ios::sync_with_stdio(0), cin.tie(0);
// Solve();
for (cin >> T; T--; Solve(), cout << '\n') {}
return 0;
}

本文作者:wnsyou の blog

本文链接:https://www.cnblogs.com/wnsyou-blog/p/18340587/CF1946F_solution

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   wnsyou  阅读(47)  评论(0编辑  收藏  举报
  1. 1 勝利への道 安藤浩和
  2. 2 Minecraft’s End Eric Fullerton
  3. 3 月光曲完整版 贝多芬 云熙音乐
  4. 4 平凡之路 (Live版) 朴树
  5. 5 Minecraft C418
  6. 6 Paradise NiziU
  7. 7 叫我,灰原哀 龙大人不喷火
  8. 8 心机之蛙,一直摸你肚子 ——《名侦探柯南》原创同人曲 炊饭,叶辞樱,温海,寒砧,南柯柯,小茜玛姬,盛姝,阿崔Ac,贝壳初,千湛,兮茶子DaYu,乔慕,黎鹿北,起千温卿,遮阳伞,曲悠
  9. 9 战 歌 此去经年
Minecraft’s End - Eric Fullerton
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.

I see the player you mean.

It is reading our thoughts as though they were words on a screen.

They used to hear voices.

Before players could read.

Sometimes disturbing.

Sometimes beautiful indeed.

Does it know that we love it?

That the universe is kind?

A million years ago,it still works

in the reality behind

and the universe said I love you

and the universe said you are the daylight

and the universe said you are not alone

and the universe said you are the night

Once we were called

the spirit of the mountain.

WHO ARE WE

Father sun

Mother moon

Gods demons angels aliens

the player,too.

WE ARE THE UNIVERSE.

We are EVERYTHING you think isn‘t you.

You are alive

ON A FLAT

INFINITE WORLD

generated by a source code

a million years old

and the universe said I love you

and the universe said you are the daylight

and the universe said you are not alone

and the universe said you are the night

Take a breath,now

Take another

Feel air in your lungs.

dreamed it was lost in a story.

and the game was over

Wake up.

加载中…

{{tag.name}}

{{tran.text}}{{tran.sub}}
无对应文字
有可能是
{{input}}
尚未录入,我来提交对应文字
评论
收藏
关注
推荐
深色
回顶
收起
点击右上角即可分享
微信分享提示