叁仟柒佰万(mex+线段树+dp+前缀和优化+双指针+桶)

叁仟柒佰万

  • problem
  • solution
  • code(50’)
  • code(90’)
  • code(100’)

problem

多组数据。

给定一个序列 aaa,你可以将它划分成任意多段,满足每一个段的 mex 相同。

求方案数,对 109+710^9+7109+7 取模。

T≤10,n≤3e5T\le 10,n\le 3e5T10,n3e5

另有一组数据 T=1,n=3e7T=1,n=3e7T=1,n=3e7

solution

observation :最后合法划分方案的 mex 一定是相同的。

在考场上,没有必要去仔细证明,想想就是。出现过的数一定不可能成为 mex

就从最小的 000 考虑,当它出现时,必定会让最后答案的 mex >0>0>0,因为不管这个 000 出现在哪里,那个段的 mex 都不能是 000

令全局 mexmexmexkkk,则说明 0∼k−10\sim k-10k1 的数都存在于数列中而 kkk 不存在。

假设最后每个区间的 mexmexmex 均为 xxx

  • x<kx<kx<k,由于序列中为 xxx 的数存在,xxx 必定在其中一个区间中,与所有区间 mex=xmex=xmex=x 矛盾。
  • x>kx>kx>k,由于不存在 kkk,显然不合法。

对于 30%30\%30% 的数据 n≤100n\le 100n100,是属于基础暴力部分分的。

直接列 dpi,j:dp_{i,j}:dpi,j: 到第 iii 个数划分了 jjj 段的方案数。

枚举上一个数的划分点 dpk−1,j−1→dpi,jdp_{k-1,j-1}\rightarrow dp_{i,j}dpk1,j1dpi,j。其中要满足 [k,i][k,i][k,i] 一段的 mex 是与前一个相同的。

但是仔细想想,发现无非就是 fk−1→fif_{k-1}\rightarrow f_{i}fk1fi,具体分了多少段其实并不需要记录,因为题目没有对段数进行限制。

这样就将第二维去掉了,时间复杂度就去了一个 O(n)O(n)O(n)

问题就来到怎么处理一段区间内的 mex。这不禁让我想到了之前做过的一道题👉链接。

0∼n0\sim n0n 建立权值线段树,对于每个 iii,将 aia_iai 对应线段树上叶子的权值置为 iii

从左往右做,每次直接查询 [0,mex)[0,mex)[0,mex) 区间内的最小值,就是最大的小于 iii 的满足条件的 kkk

你会马上反应过来,所有 k′≤kk'\le kkkk′k'k 都满足这样的条件了,都会对 dpi,jdp_{i,j}dpi,j 产生贡献。

每次,你可以线段树 O(logn)O(logn)O(logn) 求出 kkk 后再枚举 k′k'k,时间复杂度为 O(Tnlog⁡n+Tn2)O(Tn\log n+Tn^2)O(Tnlogn+Tn2),针对 50%50\%50% 的数据。

马上就知道,这是一个前缀和优化的过程。时间复杂度又可以将为 O(Tnlog⁡n)O(Tn\log n)O(Tnlogn),针对 90%90\%90% 的数据。

所以这道题只要会求 mex 的那个线段树技巧,拿到 90′90'90 的高分已经很不错了,近乎是将这道题 ACACAC

最后就是 O(n)O(n)O(n) 的正解。

observation:对于同一个右端点,其左端点对应的 mex 是单调的。【上面已经有所体现,这里只是规范化的表达】

所以可以用双指针和桶维护区间内的 mex 是否是全局的 mex(k) 即可。【具体可看代码实现】

code(50’)

#include <bits/stdc++.h>
using namespace std;
#define maxn 3005
#define int long long
#define mod 1000000007
#define inf 0x7f7f7f7f
int T, n;
bool vis[maxn];
int a[maxn], f[maxn], t[maxn << 2];#define lson now << 1
#define rson now << 1 | 1
#define mid ( ( l + r ) >> 1 )void build( int now, int l, int r ) {t[now] = 0;if( l == r ) return;build( lson, l, mid );build( rson, mid + 1, r );
}void modify( int now, int l, int r, int pos, int k ) {if( l == r ) { t[now] = k; return; }if( pos <= mid ) modify( lson, l, mid, pos, k );else modify( rson, mid + 1, r, pos, k );t[now] = min( t[lson], t[rson] );
}int query( int now, int l, int r, int L, int R ) {if( R < l or r < L ) return inf;if( L <= l and r <= R ) return t[now];return min( query( lson, l, mid, L, R ), query( rson, mid + 1, r, L, R ) );
}signed main() {freopen( "clods.in", "r", stdin );freopen( "clods.out", "w", stdout );scanf( "%lld", &T );while( T -- ) {memset( f, 0, sizeof( f ) );memset( vis, 0, sizeof( vis ) );scanf( "%lld", &n ); int x;for( int i = 1;i <= n;i ++ ) scanf( "%lld", &a[i] ), vis[a[i]] = 1;for( int i = 0;i <= n;i ++ ) if( ! vis[i] ) { x = i; break; }f[0] = 1;build( 1, 0, n );for( int i = 1;i <= n;i ++ ) {modify( 1, 0, n, a[i], i );int k = query( 1, 0, n, 0, x - 1 );if( k == inf and x ) continue;if( k == inf ) k = i;for( int j = 0;j < k;j ++ ) f[i] = ( f[i] + f[j] ) % mod;}printf( "%lld\n", f[n] );}return 0;
}

code(90’)

#include <bits/stdc++.h>
using namespace std;
#define maxn 300005
#define int long long
#define mod 1000000007
#define inf 0x7f7f7f7f
int T, n;
bool vis[maxn];
int a[maxn], f[maxn], g[maxn], t[maxn << 2];#define lson now << 1
#define rson now << 1 | 1
#define mid ( ( l + r ) >> 1 )void build( int now, int l, int r ) {t[now] = 0;if( l == r ) return;build( lson, l, mid );build( rson, mid + 1, r );
}void modify( int now, int l, int r, int pos, int k ) {if( l == r ) { t[now] = k; return; }if( pos <= mid ) modify( lson, l, mid, pos, k );else modify( rson, mid + 1, r, pos, k );t[now] = min( t[lson], t[rson] );
}int query( int now, int l, int r, int L, int R ) {if( R < l or r < L ) return inf;if( L <= l and r <= R ) return t[now];return min( query( lson, l, mid, L, R ), query( rson, mid + 1, r, L, R ) );
}const int Mxdt=100000; 
inline char gc(){static char buf[Mxdt],*p1=buf,*p2=buf;return p1==p2&&(p2=(p1=buf)+fread(buf,1,Mxdt,stdin),p1==p2)?EOF:*p1++;
}
inline int read(){int t=0,f=0;char v=gc();while(v<'0')f|=(v=='-'),v=gc();while(v>='0')t=(t<<3)+(t<<1)+v-48,v=gc();return f?-t:t;
}signed main() {freopen( "clods.in", "r", stdin );freopen( "clods.out", "w", stdout );T = read();while( T -- ) {memset( f, 0, sizeof( f ) );memset( vis, 0, sizeof( vis ) );n = read(); int x;for( int i = 1;i <= n;i ++ ) a[i] = read(), vis[a[i]] = 1;for( int i = 0;i <= n;i ++ ) if( ! vis[i] ) { x = i; break; }g[0] = 1;build( 1, 0, n );for( int i = 1;i <= n;i ++ ) {modify( 1, 0, n, a[i], i );int k = query( 1, 0, n, 0, x - 1 );if( k == inf and x ) continue;if( k == inf ) k = i;f[i] = g[k - 1];g[i] = ( g[i - 1] + f[i] ) % mod;}printf( "%lld\n", f[n] );}return 0;
}

code(100’)

#include <bits/stdc++.h>
using namespace std;
#define mod 1000000007
#define ll long long
#define maxn 37000005
int n, T;
int a[maxn], f[maxn], vis[maxn];const int Mxdt=100000; 
inline char gc(){static char buf[Mxdt],*p1=buf,*p2=buf;return p1==p2&&(p2=(p1=buf)+fread(buf,1,Mxdt,stdin),p1==p2)?EOF:*p1++;
}
inline int read(){int t=0,f=0;char v=gc();while(v<'0')f|=(v=='-'),v=gc();while(v>='0')t=(t<<3)+(t<<1)+v-48,v=gc();return f?-t:t;
}int main() {freopen( "clods.in", "r", stdin );freopen( "clods.out", "w", stdout );T = read();while( T -- ) {n = read();if( n == 37000000 ) {int x = read(), y = read();for( int i = 2;i <= n;i ++ ) vis[a[i] = ( 1ll * a[i - 1] * x + y + i ) & 262143] = 1; }elsefor( int i = 1;i <= n;i ++ ) vis[a[i] = read()] = 1;int mex;for( int i = 0;i <= n;i ++ ) if( ! vis[i] ) { mex = i; break; }for( int i = 0;i <= n;i ++ ) vis[i] = f[i] = 0; int pos = 0;for( int i = 1;i <= n;i ++ ) {vis[a[i]] ++;while( vis[pos] ) pos ++;if( pos >= mex ) { pos = i; break; }}int sum = 1, now = 1; -- vis[a[pos]];for( int i = pos;i <= n;i ++ ) {++ vis[a[i]];while( now < i and ( a[now] > mex or vis[a[now]] > 1 ) ) {sum = ( 1ll * sum + f[now] ) % mod;-- vis[a[now]];++ now;}f[i] = sum;}printf( "%d\n", f[n] );for( int i = 0;i <= n;i ++ ) vis[i] = 0;}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/316759.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

模板:吉司机线段树

所谓吉司机线段树&#xff0c;就是吉司机种的线段树 &#xff08;逃&#xff09; 解析 之前也看过一些相关内容的博客&#xff0c;但是因标记乱七八糟&#xff0c;感觉过于高深而放弃了… 直到看到洛谷这篇博客&#xff0c;完全颠覆了我的认知。&#xff08;怎么感觉语气像营…

现身说法:实际业务出发分析百亿数据量下的多表查询优化

今天给大家带来的讨论主题是通过实战经验来对百亿数据量下的多表数据查询进行优化&#xff0c;俗话说的好&#xff0c;一切脱离业务的架构都是耍流氓&#xff0c;接下来我就整理一下今天早上微信群里石头哥给大家分享的百亿数据量多表查询架构以及优化思路。由于本文内容整理自…

Help Jimmy POJ - 1661

Help Jimmy POJ - 1661 题意&#xff1a; 场景中包括多个长度和高度各不相同的平台。地面是最低的平台&#xff0c;高度为零&#xff0c;长度无限。 Jimmy老鼠在时刻0从高于所有平台的某处开始下落&#xff0c;它的下落速度始终为1米/秒。当Jimmy落到某个平台上时&#xff0c…

[HDU 6643] Ridiculous Netizens(点分治+根号分治+dp)

HDU 6643 Ridiculous Netizens problem hdu6643 题目大意&#xff1a;给定一棵无根树&#xff0c;以及每个点的点权 wiw_iwi​。 定义一个连通块的价值为连通块内点的点权之积。 求有多少个连通块价值 ≤m\le m≤m。 n≤2e3,m≤1e6n\le 2e3,m\le 1e6n≤2e3,m≤1e6。 solu…

SP422 TRANSP2 - Transposing is Even More Fun(Burnside引理,莫比乌斯反演)

解析 很巧妙的题。 关键是要利用好边长为2的整数次幂的性质。 对下标从1开始党极不友好。 首先显然答案就是 2ab2^{ab}2ab -环。 让下标均从0开始。 对于一个点 (i,j)(i,j)(i,j)&#xff0c;它原来的内存地址为 i∗2aji*2^aji∗2aj&#xff0c;转置后的地址为 j∗2bij*2^bij∗…

Fireworks(2020 ICPC南京)

Fireworks 题意&#xff1a; 你每做一个烟花要n分钟&#xff0c;释放已做好的所有烟花需要m分钟&#xff0c;每只烟花成功释放的概率为p。问你在采取最优策略的前提下&#xff0c;直到成功释放第一个烟花时最小的期望时间花费。 题解&#xff1a; 最佳策略是&#xff1a;每…

ASP.NET Core 沉思录 - ServiceProvider 的二度出生

ASP.NET Core 终于将几乎所有的对象创建工作都和依赖注入框架集成了起来。并对大部分的日常工作进行了抽象。使得整个框架扩展更加方便。各个部分的集成也更加容易。今天我们要思考的部分仍然是从一段每一个工程中都大同小异的代码开始的。IWebHostBuilder CreateWebHostBuilde…

[SPOJ - FTOUR2] Free tour II(点分治 + 背包dp + 启发式合并)

SPOJ - FTOUR2 Free tour II problem 给定一棵树&#xff0c;以及 mmm 个拥挤城市编号&#xff0c;选择一条最多包含 kkk 个拥挤城市的简单路径。 每条边有一个有趣度 www&#xff0c;可正可负。简单路径的价值定义为包含边的有趣度之和。 求最大价值。n≤2e5,∣w∣≤1e4n\…

PKUSC2022 游记

前言 1001822698014095235。 题的难度感觉比去年难不少&#xff0c;主要的体现在于两天的T1都没有之前那么可做了&#xff0c;在信息差的影响下几乎成了两场崩盘场。 由于比赛时间变短的原因&#xff0c;模拟反而比历年简单不少。 遗憾&#xff1a; d1t3的网络流莫名其妙无法…

Acwing 216. Rainbow的信号

Acwing 216. Rainbow的信号 题意&#xff1a; 给你n个数&#xff0c;在这n个数中&#xff0c;等概率地选取两个数l&#xff0c;r&#xff0c;如果l>r,则交换l,r 把信号中的第 l 个数到第 r 个数取出来&#xff0c;构成一个数列 P。 A 部分对话的密码是数列 P 的 xor 和的…

微软开源故事 | 开启 .NET 开源革命

如今&#xff0c;在微软构建开源软件是很正常的一件事——但早在2007年&#xff0c;我开始在微软工作时&#xff0c;情况并非如此。我们花了几年的时间才找到正确的方法&#xff0c;顺利开启了微软的开源之路。但是&#xff0c;如今我们已取得胜利&#xff0c;可以面带微笑地回…

【无码专区9】序列统计(带权并查集 + 前缀和建边 + dp)

因为只有std&#xff0c;没有自我实现&#xff0c;所以是无码专区 主要是为了训练思维能力 solution才是dls正解&#xff0c;但是因为只有潦草几句&#xff0c;所以大部分会有我自己基于正解上面的算法实现过程&#xff0c;可能选择的算法跟std中dls的实现不太一样。 std可能…

Acwing 217. 绿豆蛙的归宿

Acwing 217. 绿豆蛙的归宿 题意&#xff1a; 给出一个有向无环的连通图&#xff0c;起点为 1&#xff0c;终点为 N&#xff0c;每条边都有一个长度。 数据保证从起点出发能够到达图中所有的点&#xff0c;图中所有的点也都能够到达终点。 绿豆蛙从起点出发&#xff0c;走向…

LNOI2022:游记

前言 The world is cruel. 真的为身边的一些人感到可惜… Day -1 PKUSC刚刚考完&#xff0c;然后就要省选了&#xff1f; 板子实在是看的够够的了。 然而还是不想深度做题&#xff0c;看了看APIO的practise&#xff0c;T1写完发现偶数还得特别做&#xff0c;就感觉很麻烦&…

合肥.NET技术社区首次线下聚会全程回顾【多图】

2019年3月16日对于合肥.NET来说是一个特别的日子&#xff0c;因为这是合肥.NET技术社区首次非正式线下聚会&#xff01;这次聚会受场地限制&#xff08;毕竟是聚餐的形式&#xff09;&#xff0c;即使换成了小椅子后&#xff0c;最多也只能容纳24个人&#xff0c;所以还有一些小…

【无码专区10】第K大查询(双向链表 /主席树+st表)

已自我实现&#xff0c;但还是归入无码专区序列。哈哈哈哈哈 对于my idea部分&#xff0c;我的每一个想法都实现了&#xff0c;可供参考。 problem 给定一个 1∼n1\sim n1∼n 的排列和 kkk&#xff0c;求所有 r−l1≥kr-l1\ge kr−l1≥k 的区间 [l,r][l,r][l,r] 中的第 kkk 大…

SignalR第一节-在5分钟内完成通信连接和消息发送

前言首先声明&#xff0c;这又是一个小白从入门到进阶系列。 SignalR 这个项目我关注了很长时间&#xff0c;中间好像还看到过微软即将放弃该项目的消息&#xff0c;然后我也就没有持续关注了&#xff0c;目前的我项目中使用的是自己搭建的 WebSocket &#xff0c;连接管理和消…

P5327 [ZJOI2019]语言(线段树合并、生成树)

解析 只会扫描线树剖的三只log&#xff08;悲 考虑对每个 uuu 考虑合法的 vvv 的集合&#xff0c;必然是一个联通块。 进一步的&#xff0c;观察到这个联通块就是由所有经过 uuu 的路径的端点形成的最小生成树。 我们有一个最小生成树的经典结论&#xff1a;最小生成树边权和…

【学习笔记】信息学竞赛中的概率与期望小结

信息竞赛——概率与期望事件事件的蕴含、包含事件的互斥事件的对立事件的和&#xff08;并&#xff09;事件的积&#xff08;交&#xff09;事件的差概率事件的独立性全概率公式贝叶斯公式概率DP&#xff08;竞赛中的考察&#xff09;期望&#xff08;竞赛中的考察&#xff09;…

Acwing 218. 扑克牌

Acwing 218. 扑克牌 题意&#xff1a; 一副扑克牌(54张)&#xff0c;问得到A 张黑桃、B 张红桃、C 张梅花、D 张方块需要翻开的牌的张数的期望值 E 是多少&#xff1f; 如果翻开的牌是大王或者小王&#xff0c;Admin 将会把它作为某种花色的牌放入对应堆中&#xff0c;使得放…