1. 程式人生 > >洛谷P3674 小清新人渣的本願

洛谷P3674 小清新人渣的本願

題意:多次詢問,區間內是否存在兩個數,使得它們的和為x,差為x,積為x。

n,m,V <= 100000

解:

毒瘤bitset......

假如我們有詢問區間的一個桶,那麼我們就可以做到O(n)列舉查找了。

然後我們用bitset優化一下......外面套上莫隊來維護桶。

具體來說,差為x可以寫成 a - b = x

然後我們把bitset左移/右移x位,與原來的and一下,看是否有元素為1即可。

和為x可以寫成 a + b = x   N - a - b = N - x   (N - a) - b = N - x

這啟示我們維護一個N - x的反桶,然後把反桶右移N - x位與原桶and。

關於積,直接n0.5暴力即可。

  1 #include <cstdio>
  2 #include <bitset>
  3 #include <cmath>
  4 #include <algorithm>
  5 
  6 const int N = 100010;
  7 
  8 int fr[N], a[N], bin[N];
  9 std::bitset<N> bs, bs2, tp;
 10 
 11 struct ASK {
 12     int f, l, r, x, t, ans;
 13     inline bool
operator <(const ASK &w) const { 14 if(fr[l] != fr[w.l]) { 15 return l < w.l; 16 } 17 return r < w.r; 18 } 19 }ask[N]; 20 21 inline bool cmp(const ASK &A, const ASK &B) { 22 return A.t < B.t; 23 } 24 25 inline void add(int
x) { 26 if(!bin[a[x]]) { 27 bs.set(a[x]); 28 bs2.set(N - a[x]); 29 } 30 bin[a[x]]++; 31 return; 32 } 33 34 inline void del(int x) { 35 bin[a[x]]--; 36 if(!bin[a[x]]) { 37 bs.reset(a[x]); 38 bs2.reset(N - a[x]); 39 } 40 return; 41 } 42 43 int main() { 44 int n, m; 45 scanf("%d%d", &n, &m); 46 int T = sqrt(n); 47 for(int i = 1; i <= n; i++) { 48 scanf("%d", &a[i]); 49 fr[i] = (i - 1) / T + 1; 50 } 51 for(int i = 1; i <= m; i++) { 52 scanf("%d%d%d%d", &ask[i].f, &ask[i].l, &ask[i].r, &ask[i].x); 53 ask[i].t = i; 54 } 55 std::sort(ask + 1, ask + m + 1); 56 57 int l = 1, r = 1; 58 bin[a[1]]++; 59 bs.set(a[1]); 60 bs2.set(N - a[1]); 61 for(int i = 1; i <= m; i++) { 62 while(l > ask[i].l) { 63 add(--l); 64 } 65 while(r < ask[i].r) { 66 add(++r); 67 } 68 while(l < ask[i].l) { 69 del(l++); 70 } 71 while(r > ask[i].r) { 72 del(r--); 73 } 74 // ------------ 75 if(ask[i].f == 1) { 76 tp = bs & (bs >> ask[i].x); 77 ask[i].ans = tp.any(); 78 } 79 else if(ask[i].f == 2) { 80 tp = bs & (bs2 >> (N - ask[i].x)); 81 ask[i].ans = tp.any(); 82 } 83 else { 84 bool fd = 0; 85 for(int j = 1; j * j <= ask[i].x; j++) { 86 if(ask[i].x % j) { 87 continue; 88 } 89 if(bs[j] && bs[ask[i].x / j]) { 90 ask[i].ans = 1; 91 break; 92 } 93 } 94 } 95 } 96 97 std::sort(ask + 1, ask + m + 1, cmp); 98 for(int i = 1; i <= m; i++) { 99 if(ask[i].ans) { 100 puts("hana"); 101 } 102 else { 103 puts("bi"); 104 } 105 } 106 return 0; 107 }
AC程式碼