【每日題解 #16】LGP2801 教主的魔法
阿新 • • 發佈:2018-08-06
pan new lap ons sed red long b- 技術
題目鏈接 : P2801 教主的魔法
這是第一次A分塊的題
就是模板題了
每個塊內排序 每個整塊僅需維護整塊的修改量
詢問操作:
對於邊緣塊 直接暴力找在[l, r]內 且比給定值大的有幾個
對於整塊 二分查找不小於 (給定值 - 本塊修改量) 的塊有多少個
修改操作:
邊緣塊直接修改
整塊在修改量標記上修改
本題細節較多 尤其是修改和詢問的範圍
【明明是蒟蒻不熟練。。。
附上代碼:
1 #include <cstdio> 2 #include <algorithm> 3 #include <cmath> 4 using namespaceView Codestd; 5 const int N = 1e6 + 5; 6 struct Node{ 7 int bl, id; 8 long long x; 9 }node[N]; 10 int n, blo, q, ts; 11 long long atag[N];//修改量標記 12 13 bool rule1(Node a, Node b){ 14 return a.x < b.x; 15 } 16 //把[a, b]的元素加c 17 void add(int a, int b, long long c){ 18 for(int i = (node[a].bl - 1) * blo + 1; i <= min(b, min(n, node[a].bl * blo)); i++) 19 if(node[i].id >= a) 20 node[i].x += c; 21 sort(node + (node[a].bl - 1) * blo + 1, node + min(n, node[a].bl * blo) + 1, rule1); 22 if(node[a].bl != node[b].bl) 23 for(int i = (node[b].bl - 1) * blo + 1; i <= min(n, node[b].bl * blo); i++) 24 if(node[i].id <= b) 25 node[i].x += c; 26 sort(node + (node[b].bl - 1) * blo + 1, node + min(n, node[b].bl * blo) + 1, rule1); 27 for(int i = node[a].bl + 1; i <= node[b].bl - 1; i++) 28 atag[i] += c; 29 } 30 //二分查找pos塊中比a大的元素個數 31 int find(int pos, long long a){ 32 if(a > node[min(n, pos * blo)].x) return 0; 33 int l = (pos - 1) * blo + 1, r = min(n, pos * blo), mid; 34 while(l < r){ 35 mid = l + ((r - l) >> 1); 36 if(node[mid].x >= a) r = mid; 37 else l = mid + 1; 38 } 39 return min(n, pos * blo) - l + 1; 40 } 41 //詢問 [a, b]中大於等於c的元素個數 42 int query(int a, int b, long long c){ 43 int ans = 0; 44 for(int i = (node[a].bl - 1) * blo + 1; i <= min(b, min(n, node[a].bl * blo)); i++) 45 if(node[i].id >= a && node[i].x >= c - atag[node[a].bl]) 46 ans++; 47 48 if(node[a].bl != node[b].bl) 49 for(int i = (node[b].bl - 1) * blo + 1; i <= min(n, node[b].bl * blo); i++) 50 if(node[i].id <= b && node[i].x >= c - atag[node[b].bl]) 51 ans++; 52 53 for(int i = node[a].bl + 1; i <= node[b].bl - 1; i++) 54 ans += find(i, c - atag[i]); 55 return ans; 56 } 57 58 int main(){ 59 scanf("%d%d", &n, &q); 60 blo = sqrt(n); 61 for(int i = 1; i <= n; i++) scanf("%d", &node[i].x); 62 //輸入 63 for(int i = 1; i <= n; i++){ 64 node[i].bl = (i - 1) / blo + 1; 65 node[i].id = i; 66 } 67 for(int i = 1; i <= node[n].bl; i++) 68 sort(node + (i - 1) * blo + 1, node + min(n, i * blo) + 1, rule1); 69 //塊的分配與塊內排序 70 char op[10]; 71 int x, y, z; 72 for(int i = 1; i <= q; i++){ 73 scanf("%s%d%d%d", op, &x, &y, &z); 74 if(op[0] == ‘M‘) add(x, y, z); 75 else printf("%d\n", query(x, y, z)); 76 } 77 return 0; 78 }
【每日題解 #16】LGP2801 教主的魔法