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 ",Ans[i]); 61 return 0; 62 }