首页 > 代码库 > 洛谷 P3674 小清新人渣的本愿 [莫队 bitset]
洛谷 P3674 小清新人渣的本愿 [莫队 bitset]
传送门
题意:
给你一个序列a,长度为n,有Q次操作,每次询问一个区间是否可以选出两个数它们的差为x,或者询问一个区间是否可以选出两个数它们的和为x,或者询问一个区间是否可以选出两个数它们的乘积为x ,这三个操作分别为操作1,2,3
题面太强啦!!!
感觉就是莫队,想了一下分块不好搞更坚定了莫队的信念
$a-b=x$,$a=x+b$,放在权值数组上就是b右移x位,$bitset$大法好
加法同理
乘法,总共就$\sqrt{N}$个约数....
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>#include <bitset>using namespace std;typedef long long ll;const int N=1e5+5, M=2e5+5;inline ll read(){ char c=getchar();ll x=0,f=1; while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1; c=getchar();} while(c>=‘0‘&&c<=‘9‘){x=x*10+c-‘0‘; c=getchar();} return x*f;}int n, Q, a[N], op, l, r, x;int block, m, pos[N];struct meow{ int l, r, x, type, qid; bool operator <(const meow &a) const {return pos[l]==pos[a.l] ? r<a.r : pos[l]<pos[a.l];}}q[N];int ans[N];struct Meow{ bitset<M> a, b, c; int cou[N]; inline void add(int v) { cou[v]++; if(cou[v]==1) a[v]=1, b[v+N]=1, c[-v+N]=1; } inline void del(int v) { cou[v]--; if(cou[v]==0) a[v]=0, b[v+N]=0, c[-v+N]=0; } int Que(int type, int x) { //printf("Que %d %d\n",type,x); int ans=0; if(type==1) { if( (a & (a<<x)).any() ) ans=1; }else if(type==2) { if( (b & (c<<x)).any() ) ans=1; }else { int m=sqrt(x); for(int i=1; i<=m; i++) if(x%i == 0) if(cou[i] && cou[x/i]) {ans=1; break;} } return ans; }}A;void modui(){ int l=1, r=0; for(int i=1; i<=Q; i++){ while(r<q[i].r) r++, A.add(a[r]); while(r>q[i].r) A.del(a[r]), r--; while(l<q[i].l) A.del(a[l]), l++; while(l>q[i].l) l--, A.add(a[l]); ans[q[i].qid]= A.Que(q[i].type, q[i].x); }}int main(){// freopen("in","r",stdin); n=read(); Q=read(); block=sqrt(n); m=(n-1)/block+1; for(int i=1; i<=n; i++) a[i]=read(), pos[i]=(i-1)/block+1; for(int i=1; i<=Q; i++) op=read(), l=read(), r=read(), x=read(), q[i]=(meow){l, r, x, op, i}; sort(q+1, q+1+Q); modui(); for(int i=1; i<=Q; i++) puts(ans[i] ? "hana" : "bi");}
洛谷 P3674 小清新人渣的本愿 [莫队 bitset]
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。