小清新人渣的本願
這兩天寫了些的題,但都不想寫題解。。。正巧這道題還結合了莫隊,也是正在學習的,就記錄一下吧。
題意:
給定一個數組,有三種詢問:
- 詢問區間中是否有差爲的數對;
- 詢問區間中是否有和爲的數對;
- 詢問區間中是否有積爲的數對。
思路:
- 先只考慮三種詢問後面的部分,不考慮區間問題。
- 要求是否存在差爲的數對,顯然只需要知道每個數向前(或向後)的數值是否存在,要檢索所有數字的話,考慮使用的&<<()就可以知道是否存在啦!
- 要求是否存在和爲的數對,有一個小技巧,同時維護一個反轉的,想想將反轉的向右移動(數組的值域)位,肯定這個就全爲了;但如果少移動個位置的話,就相當於把原狀態中前的部分保留了,並且是反轉的;顯然將原和這個經過處理的取與,就可以知道是否有和爲的數對啦!
- 而積爲是否存在反而最簡單,考慮這個小問題的複雜度,個詢問,又是小於的,因此枚舉所有較小因數的複雜度爲,完全是可以接受的!
- 至此,此問題就只剩維護區間狀態的問題了;上述三種問題都指向了一種狀態——某個數字是否存在,這恰好是莫隊的常見問題,不難想出。因此,總複雜度爲莫隊的端點移動每個詢問的答案判斷,爲(其中和的值域都用代替了),感覺還是能被卡住的。
代碼
#include "bits/stdc++.h"
#define hhh printf("hhh\n")
#define see(x) (cerr<<(#x)<<'='<<(x)<<endl)
using namespace std;
typedef long long ll;
typedef pair<int,int> pr;
inline int read() {int x=0;char c=getchar();while(c<'0'||c>'9')c=getchar();while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();return x;}
const int maxn = 1e5+10;
const int inf = 0x3f3f3f3f;
const int mod = 1e9+7;
const double eps = 1e-7;
const int N = 100001;
int n, m, len;
int a[maxn], cnt[maxn], ans[maxn];
bitset<N+1> b1, b2;
struct P{
int opt, l, r, x, id;
friend bool operator < (const P &a, const P &b) {
if((a.l-1)/len!=(b.l-1)/len) return a.l<b.l;
if((a.l-1)/len%2) return a.r>b.r;
return a.r<b.r;
}
}p[maxn];
inline void del(int x) {
if(--cnt[x]==0) b1[x]=0, b2[N-x]=0;
}
inline void add(int x) {
if(cnt[x]++==0) b1[x]=1, b2[N-x]=1;
}
int main() {
//ios::sync_with_stdio(false); cin.tie(0);
n=read(), m=read();
for(int i=1; i<=n; ++i) a[i]=read();
for(int i=1; i<=m; ++i) {
int opt=read(), l=read(), r=read(), x=read();
p[i]=(P){opt,l,r,x,i};
}
len=sqrt(m);
sort(p+1,p+1+m);
int l=1, r=0;
for(int i=1; i<=m; ++i) {
while(l<p[i].l) del(a[l++]);
while(l>p[i].l) add(a[--l]);
while(r<p[i].r) add(a[++r]);
while(r>p[i].r) del(a[r--]);
if(p[i].opt==1) ans[p[i].id]=(b1&b1<<p[i].x).any()?1:0;
else if(p[i].opt==2) ans[p[i].id]=(b1&b2>>(N-p[i].x)).any()?1:0;
else {
bool f=0;
for(int j=1; j*j<=p[i].x; ++j) {
if(p[i].x%j==0&&b1[j]&&b1[p[i].x/j]) { f=1; break; }
}
ans[p[i].id]=f;
}
}
for(int i=1; i<=m; ++i) {
if(ans[i]) printf("hana\n");
else printf("bi\n");
}
}