1. 程式人生 > >【每日題解 #16】LGP2801 教主的魔法

【每日題解 #16】LGP2801 教主的魔法

pan new lap ons sed red long b- 技術

題目鏈接 : P2801 教主的魔法

這是第一次A分塊的題

就是模板題了

每個塊內排序 每個整塊僅需維護整塊的修改量

詢問操作:

對於邊緣塊 直接暴力找在[l, r]內 且比給定值大的有幾個

對於整塊 二分查找不小於 (給定值 - 本塊修改量) 的塊有多少個

修改操作:

邊緣塊直接修改

整塊在修改量標記上修改

本題細節較多 尤其是修改和詢問的範圍

【明明是蒟蒻不熟練。。。

附上代碼:

技術分享圖片
 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <cmath>
 4 using namespace
std; 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 }
View Code

【每日題解 #16】LGP2801 教主的魔法