luogu P2801 教主的魔法
分块好题。
想法其实特别暴力,对于每一个块,都在块内排一个序,这样查询整块的时候二分找大于等于k - add[i]的数有多少。然后块外零散的数就暴力判断好啦。
所以有两个数组b[i][……]:代表第 i 块有哪些数;add[i]是整块加标记。
然后修改的时候,对于零散的数所在块,暴力重构b数组。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<algorithm> 5 #include<cstring> 6 #include<cstdlib> 7 #include<cctype> 8 #include<vector> 9 #include<stack> 10 #include<queue> 11 using namespace std; 12 #define enter puts("") 13 #define space putchar(' ') 14 #define Mem(a, x) memset(a, x, sizeof(a)) 15 #define rg register 16 typedef long long ll; 17 typedef double db; 18 const int INF = 0x3f3f3f3f; 19 const db eps = 1e-8; 20 const int maxn = 1e6 + 5; 21 const int maxb = 1e3 + 5; 22 inline ll read() 23 { 24 ll ans = 0; 25 char ch = getchar(), last = ' '; 26 while(!isdigit(ch)) {last = ch; ch = getchar();} 27 while(isdigit(ch)) {ans = ans * 10 + ch - '0'; ch = getchar();} 28 if(last == '-') ans = -ans; 29 return ans; 30 } 31 inline void write(ll x) 32 { 33 if(x < 0) x = -x, putchar('-'); 34 if(x >= 10) write(x / 10); 35 putchar(x % 10 + '0'); 36 } 37 38 int n, q, a[maxn]; 39 char c[2]; 40 41 int S, Cnt = 0, blo[maxn], lb[maxn], rb[maxn]; 42 int b[maxb][maxb], add[maxb]; 43 void init() 44 { 45 S = sqrt(n); 46 Cnt = n % S ? n / S : n / S + 1; 47 for(int i = 1; i <= Cnt; ++i) lb[i] = (i - 1) * S, rb[i] = i * S - 1; 48 rb[Cnt] = n; 49 for(int i = 1, j = 1; i <= n; ++i) blo[i] = j, j += (i == rb[j]); 50 for(int i = 1, cb = 0; i <= Cnt; ++i, cb = 0) 51 { 52 for(int j = lb[i]; j <= rb[i]; ++j) b[i][++cb] = a[j]; 53 sort(b[i] + 1, b[i] + cb + 1); 54 } 55 } 56 void update(int L, int R, int k) 57 { 58 int l = blo[L], r = blo[R], cb = 0; 59 if(l == r) 60 { 61 for(int i = L; i <= R; ++i) a[i] += k; 62 for(int i = lb[l]; i <= rb[l]; ++i) b[l][++cb] = a[i]; 63 sort(b[l] + 1, b[l] + cb + 1); 64 return; 65 } 66 for(int i = l + 1; i < r; ++i) add[i] += k; 67 for(int i = L; i <= rb[l]; ++i) a[i] += k; 68 for(int i = lb[l]; i <= rb[l]; ++i) b[l][++cb] = a[i]; 69 sort(b[l] + 1, b[l] + cb + 1); 70 cb = 0; 71 for(int i = lb[r]; i <= R; ++i) a[i] += k; 72 for(int i = lb[r]; i <= rb[r]; ++i) b[r][++cb] = a[i]; 73 sort(b[r] + 1, b[r] + cb + 1); 74 } 75 int query(int L, int R, int k) 76 { 77 int l = blo[L], r = blo[R], ret = 0; 78 if(l == r) 79 { 80 for(int i = L; i <= R; ++i) ret += (a[i] + add[l] >= k); 81 return ret; 82 } 83 for(int i = l + 1; i < r; ++i) 84 { 85 int tp = lower_bound(b[i] + 1, b[i] + rb[i] - lb[i] + 2, k - add[i]) - b[i]; 86 if(tp > rb[i] - lb[i] + 1) continue; 87 ret += rb[i] - lb[i] + 1 - tp + 1; 88 } 89 for(int i = L; i <= rb[l]; ++i) ret += (a[i] + add[l] >= k); 90 for(int i = lb[r]; i <= R; ++i) ret += (a[i] + add[l] >= k); 91 return ret; 92 } 93 94 int main() 95 { 96 n = read(), q = read(); 97 for(int i = 1; i <= n; ++i) a[i] = read(); 98 init(); 99 for(int i = 1; i <= q; ++i) 100 { 101 scanf("%s", c); 102 int L = read(), R = read(), k = read(); 103 if(c[0] == 'M') update(L, R, k); 104 else write(query(L, R, k)), enter; 105 } 106 return 0; 107 }