2020牛客暑期多校训练营(第二场)G. Greater and Greater(bitset优化fft)

news/2024/7/6 1:40:19 标签: bitset, fft

题目

一个长为n(n<=150000)的序列a,第i个数ai(1<=ai<=1e9)

一个长为m(m<=min(n,40000))的序列b,第j个数bj(1<=bj<=1e9)

求a中有多少长为m的子区间S,满足对应任意[1,m],Si>=bi

思路来源

夏老师的submission

题解

暴力是O(n*m)的,6e9,考虑引入bitset除掉一个64,复杂度就稳了

独立考虑a中的每个值,能大于哪些b中的值,也就是将a和b中的值放到一起排序

遇到b的值就给bitset上赋上一位,遇到a中的值就令a的答案等于当前的bitset的值

这样bitset本质上只会变化m次,赋n次值每次操作数是m/64,总复杂度O(n*m/64)

求出这n个数的bitset后,就是一个本质fft问题,

如果a的[i,i+m-1]需要和b的[0,m-1]比,就需要满足二者下标差为i

所以可以先将b序列每个值对应的bitset翻转,也就是令j=m-1-j,

这样i-j=k转化为i+m-1-j=k+m-1,

a中[i,i+m-1]和b中[0,m-1]做比较时,就需要到下标i+m-1上找

而最终下标上的值应该是一个与操作,即只要有一位为0不合法,该区间就不合法

由于bitset与/或时,两个bitset需要等长,无法控制一个长为n,另一个长为m

两个bitset都长为n时,就会有一些不合法的位,而左移新挪出来的位默认为0

所以,这里采用的是或的方式,即令有效位为0,

如果不存在非有效位,或在一起就应该是0,

统计最终bitset的[m-1,n-1]的0的个数即可

代码

#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define per(i,a,b) for(int i=(a);i>=(b);--i)
typedef long long ll;
typedef double db;
typedef pair<int,int> P;
#define fi first
#define se second
#define dbg(x) cerr<<(#x)<<":"<<x<<" ";
#define dbg2(x) cerr<<(#x)<<":"<<x<<endl;
#define SZ(a) (int)(a.size())
#define sci(a) scanf("%d",&(a))
#define pb push_back
#define pt(a) printf("%d",a);
#define pte(a) printf("%d\n",a)
#define ptlle(a) printf("%lld\n",a)
#define debug(...) fprintf(stderr, __VA_ARGS__)
//std::mt19937_64 gen(std::chrono::system_clock::now().time_since_epoch().count());
//ll get(ll l, ll r) { std::uniform_int_distribution<ll> dist(l, r); return dist(gen); }
const int N=150010,M=40010,INF=0x3f3f3f3f;
int n,m,cnt;
struct node{
    int v,p,op;
}e[N+M];
bool operator<(node a,node b){
    if(a.v!=b.v)return a.v<b.v;
    return a.op>b.op;
}
bitset<N>tmp,ans;
/*
i-j=k(0<=k<=n-m)
i+m-1-j=k(m-1<=k<=n-1)
*/
int main(){
    //freopen("edu.out","w",stdout);
    sci(n),sci(m);
    rep(i,0,n-1)sci(e[i].v),e[i].p=i,e[i].op=1;
    rep(i,n,n+m-1)sci(e[i].v),e[i].p=i-n,e[i].op=2;
    sort(e,e+n+m);
    rep(i,0,m-1)tmp.set(i);
    rep(i,0,n+m-1){
        int p=e[i].p;
        if(e[i].op==1){
            ans|=(tmp<<p);
        }
        else{
            tmp.reset(m-1-p);
        }
        // cout<<"i:"<<i<<" v:"<<e[i].v<<" p:"<<e[i].p<<endl;
        // cout<<"ans:"<<ans.to_string()<<endl;
        // cout<<"tmp:"<<tmp.to_string()<<endl;
        // cout<<"ans0:"<<ans[0]<<endl;
    }
    //cout<<"ans:"<<ans.to_string()<<endl;
    rep(i,m-1,n-1){
        cnt-=ans[i];
    }
    printf("%d\n",cnt+n-m+1);
	return 0;
}


http://www.niftyadmin.cn/n/5070983.html

相关文章

Qt扫盲-QTreeView 理论总结

QTreeView 理论使用总结 一、概述二、快捷键绑定三、提高性能四、简单实例1. 设计与概念2. TreeItem类定义3. TreeItem类的实现4. TreeModel类定义5. TreeModel类实现6. 在模型中设置数据 一、概述 QTreeView实现了 model 中item的树形表示。这个类用于提供标准的层次列表&…

Spring IOC之AdviceModeImportSelector

博主介绍&#xff1a;✌全网粉丝4W&#xff0c;全栈开发工程师&#xff0c;从事多年软件开发&#xff0c;在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战&#xff0c;博主也曾写过优秀论文&#xff0c;查重率极低&#xff0c;在这方面有丰富的经验…

AI绘画-Stable Diffusion笔记

软件&#xff1a;Stable Diffusion 视频教程来自 https://www.bilibili.com/video/BV1As4y127HW/?spm_id_from333.337.search-card.all.click 提示词 提示词类别 内容型提示词 人物主题特征&#xff1a; 服饰穿搭&#xff1a;white dress 发型发色&#xff1a;blonde hair,l…

工程派工单,建筑工程派工单

工程派工单是指建设项目管理人员或工程维修人员发出的文件&#xff0c;用于标明工人或维修人员在建设项目或设备中处理或维修问题的任务。派工单包括建设项目的实际维护任务、所需材料、工具等信息&#xff0c;以及具体的执行人员和完成时间。工程派工单是保证建设项目顺利开展…

沈阳陪诊系统|沈阳陪诊系统开发|沈阳陪诊系统功能和优势

在现代医疗服务中&#xff0c;陪诊系统服务正变得越来越重要。这项创新的服务提供了一种全新的方式&#xff0c;帮助患者在医院就诊时获得更好的照顾和支持。无论是面对复杂的医学流程还是需要心理支持&#xff0c;陪诊系统服务都能够为患者提供方便、专业的帮助。陪诊系统服务…

Cherno C++视频课程-学习笔记

P16、P17 C指针和引用 待补充 P19 C类和结构体的对比 1.语法区别&#xff1a;仅有内部成员可见性的区别。类成员默认是private&#xff0c;而结构体成员默认是public。 2.常用方式&#xff1a; 结构体&#xff1a;常用来定义新的变量类型。也用来保持与C语言的兼容性。类&a…

Windows10点击开始菜单没反应的四种解决方法

在Windows10电脑中&#xff0c;用户点击开始菜单却出现了没反映的情况&#xff0c;这样用户就无法通过开始菜单来展开操作哦&#xff0c;会给用户的正常操作带来一定程序的影响&#xff0c;下面小编给大家带来四种简单的解决方法&#xff0c;帮助大家轻松恢复Windows10电脑开始…

New Journal of Physics:不同机器学习力场特征的准确性测试

文章信息 作者&#xff1a;Ting Han1, Jie Li1, Liping Liu2, Fengyu Li1, * and Lin-Wang Wang2, * 通信单位&#xff1a;内蒙古大学物理科学与技术学院、中国科学院半导体研究所 DOI&#xff1a;10.1088/1367-2630/acf2bb 研究背景 近年来&#xff0c;基于DFT数据的机器学…