1. 程式人生 > >3809: Gty的二逼妹子序列

3809: Gty的二逼妹子序列

3809: Gty的二逼妹子序列

連結

分析:

  和這道AHOI2013 作業差不多。權值是1~n的,所以對權值進行分塊。$O(1)$修改,$O(\sqrt n)$查詢。

程式碼:

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<iostream>
 5 #include<cmath>
 6 #include<cctype>
 7 #include<set>
 8 #include<queue>
 9
#include<vector> 10 #include<map> 11 using namespace std; 12 typedef long long LL; 13 14 inline int read() { 15 int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1; 16 for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f; 17 } 18 19 const int N = 100005
; 20 21 int bel[N], sum[N], a[N], Ans[N * 10], cnt[N], B; 22 struct Que{ 23 int l, r, a, b, id; 24 bool operator < (const Que &A) const { 25 return bel[l] == bel[A.l] ? r < A.r : bel[l] < bel[A.l]; 26 } 27 }Q[N * 10]; 28 29 inline void add(int x) { 30 cnt[x] ++;
31 if (cnt[x] == 1) sum[bel[x]] ++; 32 } 33 inline void del(int x) { 34 cnt[x] --; 35 if (cnt[x] == 0) sum[bel[x]] --; 36 } 37 inline int query(int l,int r) { 38 int res = 0; 39 for (int i = l, lim = min(r, bel[l] * B); i <= lim; ++i) res += (cnt[i] > 0); 40 if (bel[l] != bel[r]) 41 for (int i = (bel[r] - 1) * B + 1; i <= r; ++i) res += (cnt[i] > 0); 42 for (int i = bel[l] + 1; i <= bel[r] - 1; ++i) res += sum[i]; 43 return res; 44 } 45 int main() { 46 int n = read(), m = read(); B = sqrt(n); 47 for (int i = 1; i <= n; ++i) a[i] = read(); 48 for (int i = 1; i <= m; ++i) 49 Q[i].l = read(), Q[i].r = read(), Q[i].a = read(), Q[i].b = read(), Q[i].id = i; 50 for (int i = 1; i <= n; ++i) bel[i] = (i - 1) / B + 1; 51 sort(Q + 1, Q + m + 1); 52 int L = 1, R = 0; 53 for (int i = 1; i <= m; ++i) { 54 while (L > Q[i].l) add(a[--L]); 55 while (R < Q[i].r) add(a[++R]); 56 while (L < Q[i].l) del(a[L++]); 57 while (R > Q[i].r) del(a[R--]); 58 Ans[Q[i].id] = query(Q[i].a, Q[i].b); 59 } 60 for (int i = 1; i <= m; ++i) printf("%d\n",Ans[i]); 61 return 0; 62 }