题目链接:点击查看

题目大意:k-bag 序列的定义是由多个 1 ~ k 的排列顺序连接起来的序列,现在问给定的序列是不是 k-bag 的连续子串

题目分析:读完题目后,如果给定的序列是 k-bag 的连续子串的话,那么可以将所有情况都分为以下三种类型:

  1. 一个部分k-bag的前缀 + 数个(至少一个)完整的k-bag + 一个部分k-bag的后缀
  2. 一个部分k-bag的前缀 + 一个部分k-bag的后缀
  3. 一个部分k-bag

判断部分k-bag和完整的k-bag需要用到两种不同的方法,判断部分k-bag的话,只需要判断区间内的每个数都是否不同即可,即区间的长度等于区间内不同的数的个数,这个利用 dp 和 unordered_map 搭配就能 O( n ) 的时间内预处理出来了,这里用 cnt1[ i ] 表示 1 ~ i 内有多少个不同的数(前缀),cnt2[ i ] 表示 i ~ n 内有多少个不同的数(后缀)

接下来需要判断完整的k-bag,如果也是用 “ 区间内有多少个不同的数 ” 去判断的话,需要用到主席树,但可能会超时(群友是这样说的),而且代码复杂度也大大上升,很容易写崩,这里用到一种哈希的方法,不会证明只会用,大概就是一个连续的序列 [ l , r ] ,维护 sum 和 xor ,sum = l + ( l + 1 ) + ... + ( r - 1 ) + r ,xor = l ^ ( l + 1 ) ^ ... ^ ( r - 1 ) ^ r ,形成一个二元对 < sum , xor > ,这个二元对和 [ l , r ] 是一一对应的,可以称之为 RSB哈希 ( rsb学长自己起的名字 )

上面开个小玩笑,回到这个题目中来,我们可以再次 O( n ) 维护一下整个数列的 sum前缀和 和 xor前缀异或和,然后再小分一下类,当 k < n 时,只会有上面的情况 1 和情况 2 ,这样我们可以枚举 [ 1 , k ] 作为滑动窗口的起点,然后检查每个长度为 k 的滑动窗口,对于每个长度为 k 的滑动窗口,我们现在可以 O( 1 ) 求出当前窗口的xor之和以及sum之和,判断一下是否等于 1 ~ k 的 xor 和 sum 就好了,当 k >= n 时,就只有情况 2 和情况 3 了,此时我们可以当做情况 2 处理,O( n ) 枚举一下断点,将整个数列分割成前半部分和后半部分,如果某次分割下,前半部分和后半部分满足了情况 2 的话,那么显然答案就是 YES 了,相反,如果上面三种情况都不满足的话,答案就是 NO 了

时间复杂度为 O( n ) ,如果不计 unordered_map 的常数的话

代码:

#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
#include<bitset>
#include<unordered_map>
using namespace std;typedef long long LL;typedef unsigned long long ull;const int inf=0x3f3f3f3f;const int N=5e5+100;int a[N],n,k;LL sum[N],Xor[N],SUM,XOR;unordered_map<int,int>mp;int cnt1[N],cnt2[N];//cnt1[i]:1~i内有多少个不同的数,cnt2[i]:i~n内有多少个不同的数bool check(int st)//检查以st为起点的滑动窗口是否满足条件
{for(int i=st;i<=n;i+=k){int l=i,r=i+k-1;if(r<=n){if(sum[r]-sum[l-1]!=SUM||(Xor[r]^Xor[l-1])!=XOR)return false;}else return cnt2[l]==n-l+1;}return true;
}bool solve()
{if(k<n)//情况1和情况2{                      SUM=0,XOR=0;for(int i=1;i<=k;i++)//O(k)处理一下1~k的xor和sum作为标准{SUM+=i;XOR^=i;}for(int i=1;i<=k;i++)//枚举起点位置{if(cnt1[i-1]!=i-1)break;if(check(i))return true;}}else//情况2和情况3{for(int i=2;i<=n;i++)//枚举断点if(cnt1[i-1]==i-1&&cnt2[i]==n-i+1)return true;}return false;
}void init()//预处理cnt1和cnt2
{mp.clear();cnt1[0]=0;for(int i=1;i<=n;i++){cnt1[i]=cnt1[i-1];if(!mp[a[i]])cnt1[i]++;mp[a[i]]++;}mp.clear();cnt2[n+1]=0;for(int i=n;i>=1;i--){cnt2[i]=cnt2[i+1];if(!mp[a[i]])cnt2[i]++;mp[a[i]]++;}
}int main()
{
#ifndef ONLINE_JUDGE
//  freopen("data.in.txt","r",stdin);
//  freopen("data.out.txt","w",stdout);
#endif
//  ios::sync_with_stdio(false);int w;cin>>w;while(w--){scanf("%d%d",&n,&k);bool flag=true;//判断数列的每个元素是否位于1~k之间for(int i=1;i<=n;i++){scanf("%d",a+i);if(a[i]<1||a[i]>k)flag=false;sum[i]=sum[i-1]+a[i];Xor[i]=Xor[i-1]^a[i];}if(!flag){puts("NO");continue;}init();if(solve())puts("YES");elseputs("NO");}return 0;
}

牛客多校6 - K-Bag(哈希+滑动窗口)相关推荐

  1. 2021牛客多校10 - Browser Games(哈希)

    题目链接:点击查看 题目大意:给出 nnn 个字符串,对于每个 iii ,输出最少需要用多少个前缀,可以表示第 1∼i1\sim i1∼i 个字符串而不能表示第 i+1∼ni+1\sim ni+1∼n ...

  2. LCS(2021牛客多校4)

    LCS(2021牛客多校4) 题意: 让你构造三个字符串s1,s2,s3,长度均为n,要求LCS(s1,s2)=a,LCS(s2,s3)=b,LCS(s1,s3)=c 题解: 先考虑三个串互相LCS为 ...

  3. 24dian(牛客多校第三场)

    24dian(牛客多校第三场) 题意: 给你n张牌,每张牌的大小为1 ~ 13,问这些牌与加减乘除任意组合(可以使用括号),且但所有的有效解在计算过程中都涉及到分数,即非整数,能否组成答案m,如果可以 ...

  4. 2019牛客多校第四场 I题 后缀自动机_后缀数组_求两个串de公共子串的种类数

    目录 求若干个串的公共子串个数相关变形题 对一个串建后缀自动机,另一个串在上面跑同时计数 广义后缀自动机 后缀数组 其他:POJ 3415 求两个串长度至少为k的公共子串数量 @(牛客多校第四场 I题 ...

  5. 2022牛客多校(十)

    2022牛客多校(十) 一.比赛小结 比赛链接:"蔚来杯"2022牛客暑期多校训练营10 二.题目分析及解法(基础题) F.Shannon Switching Game? 题目链接 ...

  6. python字符串去重及排序 牛客_2018牛客多校第一场 D.Two Graphs

    题意: n个点,m1条边的图E1,n个点,m2条边的图E2.求图E2有多少子图跟图E1同构. 题解: 用STL的全排列函数next_permutation()枚举映射.对于每一种映射枚举每一条边判断合 ...

  7. 2019牛客多校第九场AThe power of Fibonacci(广义BM)

    2019牛客多校第九场AThe power of Fibonacci(广义BM) 题目大意 求斐波那契数列m次方的前n项和 解题思路 显然,斐波那契的m次方前缀和依然是线性递推,因此考虑用exBM求解 ...

  8. 牛客多校第四场【B-Basic Gcd Problem】

    牛客多校第四场[B-Basic Gcd Problem] 题目链接:https://ac.nowcoder.com/acm/contest/5669/B 思路:先要理解公式,多看几个数据基本就会有点想 ...

  9. 牛客多校第三场 B【Classical String Problem】

    牛客多校第三场 B[Classical String Problem] 链接:https://ac.nowcoder.com/acm/contest/5668/B 来源:牛客网 题目描述 Given ...

  10. 【2021牛客多校2】F-Girlfriend 计算几何

    2021牛客多校2-F F-Girlfriend 题目大意 给出四个点 A , B , C , D A, B, C, D A,B,C,D 另有两点 P 1 , P 2 P_1, P_2 P1​,P2​ ...

最新文章

  1. [密码学] 数字签名基础
  2. 计算机主机f不显示,为什么我不能按计算机上的f键行
  3. k8s集群部分常见问题处理
  4. iQOO Z1于10月21日开启双十一钜惠,最高立减200元
  5. python字符串_Python字符串格式化%s%d%f详解
  6. 修改oracle超空间大小,Oracle修改表空间大小详解
  7. Nginx、Apache工作原理以及nginx为何比Apache高效
  8. Matlab中的有限域计算
  9. winen中文_win10中文语言包下载|
  10. 深入理解HashMap底层数据结构
  11. 第七届山东理工大学ACM趣味编程循环赛 Round#2 sdut4120 城堡问题
  12. java 读取写入excel_java读取和写入Excel文件
  13. XAMARIN运行IPHONE模拟器
  14. python cox模型_Cox模型的基本概念_Python数据分析系列视频课程--玩转统计模型_数据挖掘与分析视频-51CTO学院...
  15. 屏蔽恼人的QQ迷你首页
  16. pvs-stdio ue4_PlatformIO中的PVS-Studio集成
  17. 浅谈统计检验效能和FDR
  18. 女生学软件测试难不难 培训出来能找到工作吗?
  19. 解析区块链游戏与GameFi的发展历程
  20. 重学c语言 新开导言

热门文章

  1. 自定义图片验证码认证过滤器
  2. MySQL分组函数使用的其他注意事项
  3. SpringSecurity 权限控制准备之IOC容器结构说明
  4. Spring-Cloud中的负载
  5. 练习_用if语句实现考试成绩划分
  6. 解决cookie写入问题
  7. c语言和plc编程,PLC编程C语言.ppt
  8. 学典教育计算机二级,层次化分类的离线中文签名真伪鉴别方法-计算机工程与应用.PDF...
  9. Linux 查看显存带宽,Vega 20规格与Vega 10相近,显存带宽翻倍,但目前只能跑Linux - 超能网 - IT帮...
  10. gif透明背景动画_常用GIF动图制作工具,抖音里面的动图都是这些工具做出来的...