luogu P2617 Dynamic Rankings(分块,n <= 1e4)
带修改区间第k大。
然而某谷把数据扩大到了1e5,所以用分块现在只能得50分。
分块怎么做呢?很暴力的。
基本思想还是块内有序,块外暴力统计。
对于修改,直接重排修改的数所在块,时间复杂度O(√nlogn√n)。
对于询问,二分答案,然后在每个块内再二分统计小于mid的数有几个,块外暴力统计,时间复杂度O(m * log1e9 * √nlog√n),所以只能过1e4。
![](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 = 1e5 + 5; 21 const int maxb = 320; 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 << 1) + (ans << 3) + 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]; 43 void init() 44 { 45 S = sqrt(n); 46 Cnt = n % S ? n / S + 1: n / S; 47 for(rg int i = 1; i <= Cnt; ++i) lb[i] = rb[i - 1] + 1, rb[i] = lb[i] + S - 1; 48 rb[Cnt] = n; 49 for(rg int i = 1, j = 1; i <= n; ++i) blo[i] = j, j += (i == rb[j]); 50 for(rg int i = 1, cb = 0; i <= Cnt; ++i, cb = 0) 51 { 52 for(rg 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 inline void update(const int& x, const int& k) 57 { 58 a[x] = k; 59 int t = blo[x], cb = 0; 60 for(rg int i = lb[t]; i <= rb[t]; ++i) b[t][++cb] = a[i]; 61 sort(b[t] + 1, b[t] + cb + 1); 62 } 63 inline int judge(const int& L, const int& R, const int& x, const int& k) 64 { 65 int l = blo[L], r = blo[R], ret = 0; 66 if(l == r) 67 { 68 for(rg int i = L; i <= R; ++i) ret += (a[i] < x); 69 return ret < k; 70 } 71 for(rg int i = l + 1; i < r; ++i) 72 { 73 int tp = lower_bound(b[i] + 1, b[i] + rb[i] - lb[i] + 2, x) - b[i] - 1; 74 if(tp < 1) tp = 0; 75 if(tp > rb[i] - lb[i]) tp = rb[i] - lb[i] + 1; 76 ret += tp; 77 } 78 for(rg int i = L; i <= rb[l]; ++i) ret += (a[i] < x); 79 for(rg int i = lb[r]; i <= R; ++i) ret += (a[i] < x); 80 return ret < k; 81 } 82 83 int main() 84 { 85 n = read(), q = read(); 86 for(rg int i = 1; i <= n; ++i) a[i] = read(); 87 init(); 88 for(rg int i = 1; i <= q; ++i) 89 { 90 scanf("%s", c); 91 if(c[0] == 'C') 92 { 93 int x = read(), y = read(); 94 update(x, y); 95 } 96 else 97 { 98 int L = read(), R = read(), k = read(); 99 int l = 0, r = 1e9; 100 while(l < r) 101 { 102 int mid = (l + r + 1) >> 1; 103 if(judge(L, R, mid, k)) l = mid; 104 else r = mid - 1; 105 } 106 write(l), enter; 107 } 108 } 109 return 0; 110 }