【BZOJ3236】【Ahoi2013】作业
题意:询问区间[L,R]内数值范围在[a,b]的数的个数 以及数值的个数。
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3236
写的莫队+树状数组QwQ(其实这是我第一次写莫队2333
1 #include <cmath> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <iostream> 5 #include <algorithm> 6 #define MaxN 100010 7 #define MaxM 1000010 8 using namespace std; 9 int n, m, sz; 10 int da[MaxN], ans1[MaxM], ans2[MaxM], cnt[MaxN], p[2][MaxN], pos[MaxN]; 11 struct rec{ 12 int l, r, a, b, pos; 13 }q[MaxM]; 14 15 int read(){ 16 int ret = 0; char c = getchar(); 17 while (c < '0' || c > '9') c = getchar(); 18 while (c >= '0' && c <= '9') ret = ret*10 + c-'0', c = getchar(); 19 return ret; 20 } 21 22 bool cmp(rec a, rec b){ 23 if (pos[a.l] == pos[b.l]) return a.r < b.r; 24 return pos[a.l] < pos[b.l]; 25 } 26 27 int lowbit(int x){ return x&(-x); } 28 29 int query(int x, int t){ 30 int ret = 0; 31 for (int i = x; i; i -= lowbit(i)){ 32 ret += p[t][i]; 33 } 34 return ret; 35 } 36 37 void updata(int x, int t, int c){ 38 for (int i = x; i <= n; i += lowbit(i)){ 39 p[t][i] += c; 40 } 41 } 42 43 void updata(int x, int k){ 44 if (!cnt[x]) updata(x, 1, 1); 45 cnt[x] += k; 46 if (!cnt[x]) updata(x, 1, -1); 47 updata(x, 0, k); 48 } 49 50 int main(){ 51 freopen("bzoj3626.in", "r", stdin); 52 freopen("bzoj3626.out", "w", stdout); 53 scanf("%d%d", &n, &m); 54 sz = (int) sqrt(n); 55 for (int i = 1; i <= n; i++) da[i] = read(), pos[i] = i/sz; 56 for (int i = 1; i <= m; i++){ 57 q[i].l = read(); q[i].r = read(); 58 q[i].a = read(); q[i].b = read(); 59 q[i].pos = i; 60 } 61 sort(q+1, q+1+m, cmp); 62 int l = 1, r = 0; 63 for (int i = 1; i <= m; i++){ 64 rec now = q[i]; 65 while (l < now.l) updata(da[l++], -1); 66 while (l > now.l) updata(da[--l], 1); 67 while (r < now.r) updata(da[++r], 1); 68 while (r > now.r) updata(da[r--], -1); 69 ans1[now.pos] = query(now.b, 0) - query(now.a-1, 0); 70 ans2[now.pos] = query(now.b, 1) - query(now.a-1, 1); 71 } 72 for (int i = 1; i <= m; i++){ 73 printf("%d %d\n", ans1[i], ans2[i]); 74 } 75 return 0; 76 }