รับอาร์เรย์และแบบสอบถามหลายรายการ นอกจากนี้ยังมีการสืบค้นข้อมูลสองประเภท กล่าวคือ การอัปเดต[ L, R ] หมายถึงการอัปเดตองค์ประกอบจาก L เป็น R ด้วยรากที่สอง และข้อความค้นหา[ L, R ] หมายถึงการคำนวณผลรวมขององค์ประกอบจาก L ถึง R เราคือ สมมติว่าอาร์เรย์ที่จัดทำดัชนีแบบอิง 1 ตัวอย่างเช่น
Input: nums[ ] = { 0, 9, 4, 1, 5, 2, 3 }, Query[ ] = { {1, 1, 3}, {2, 1, 2}, {1, 2, 5}, { 1, 4, 5}}
Output: 14
10
7
1st element of 1st query is 1 means we need to calculate range sum from 1 to 3 i.e 9 + 4 + 1 = 14
1st element of 2nd query is 2 means we need to update range element from 1 to 2 with their square roots now new arr[] array is { 3, 2, 1, 5, 2, 3 }
1st element of 3rd query is 1 means we need to calculate range sum from 2 to 5 i.e 2 + 1 + 5 + 2 = 10
1st element of the 4th query is 1 means we need to calculate the range sum from 4 to 5 i.e 5 + 2 = 7
Input: nums[] = { 0, 3, 2, 4, 16, 2 }, Query[ ] = {{1, 1, 3}, {2, 2, 5}}
Output: 9 แนวทางในการหาแนวทางแก้ไข
แนวทางง่ายๆ
เราสามารถใช้การวนซ้ำจนกว่าการสืบค้นข้อมูลจะสิ้นสุดและส่งคืนผลรวมของช่วงสำหรับการค้นหาผลรวมและอัปเดตอาร์เรย์สำหรับการสืบค้นข้อมูลอัปเดต แต่ความซับซ้อนของเวลาของโปรแกรมนี้จะเป็น O(q * n) มาหาแนวทางที่มีประสิทธิภาพกันเถอะ
แนวทางที่มีประสิทธิภาพ
โปรแกรมอาจมีประสิทธิภาพถ้าเราลดจำนวนการดำเนินการหรือจำนวนการวนซ้ำ เราสามารถใช้ Binary Indexed Trees ซึ่งเราสร้างอาร์เรย์และใช้สองฟังก์ชันสำหรับการอัปเดตและผลรวมของคิวรี สำหรับเคียวรีอัปเดต หากองค์ประกอบเป็น 1 ไม่จำเป็นต้องอัปเดตเนื่องจากสแควร์รูทจะเป็นองค์ประกอบเดียวเท่านั้น ตอนนี้ เราสามารถใช้ชุดเพื่อเก็บดัชนีที่มากกว่าหนึ่งและใช้การค้นหาแบบไบนารีเพื่อค้นหาดัชนี Lth และเพิ่มจนกระทั่งทุกองค์ประกอบช่วงได้รับการอัปเดต จากนั้นตรวจสอบว่าค่าที่อัปเดตกลายเป็นหนึ่งหรือไม่ จากนั้นลบดัชนีนั้นออกจากชุดเพราะจะเป็น 1 เสมอสำหรับการสืบค้นการอัปเดตใดๆ
สำหรับการสืบค้นผลรวม เราสามารถดำเนินการ query(R) - query(L-1)
ตัวอย่าง
รหัส C++ สำหรับแนวทางข้างต้น
#include <bits/stdc++.h>
using namespace std;
// Maximum size input array can be
const int m = 200;
// Creating Binary Indexed tree.
int binary_indexed[m + 1];
// for update query
void update_q(int a, int x, int n){
while(a <= n) {
binary_indexed[a] += x;
a += a & -a;
}
}
// Function to calculate sum range.
int sum_q(int a){
int s = 0;
while(a > 0) {
s += binary_indexed[a];
a -= a & -a;
}
return s;
}
int main(){
int no_query = 4;
int nums[] = { 0, 9, 4, 1, 5, 2, 3 };
int n = sizeof(nums) / sizeof(nums[0]);
// 2-D array for queries.
int q[no_query + 1][3];
q[0][0] = 1, q[0][1] = 1, q[0][2] = 3;
q[1][0] = 2, q[1][1] = 1, q[1][2] = 2;
q[2][0] = 1, q[2][1] = 2, q[2][2] = 5;
q[3][0] = 1, q[3][1] = 4, q[3][2] = 5;
set<int> s;
for (int i = 1; i < n; i++) {
// Inserting indexes in the set of elements that are greater than 1.
if (nums[i] > 1)
s.insert(i);
update_q(i, nums[i], n);
}
for (int i = 0; i < no_query; i++) {
// Checking 0th index for update query or sum query.
if (q[i][0] == 2) {
while (true) {
// Finding the left index using binary search
auto it = s.lower_bound(q[i][1]);
// checking whether it reaches right index.
if (it == s.end() || *it > q[i][2])
break;
q[i][1] = *it;
// updating array element to their square roots.
update_q(*it, (int)sqrt(nums[*it]) - nums[*it], n);
nums[*it] = (int)sqrt(nums[*it]);
//checking if updated value is 1 the removing it from set
if (nums[*it] == 1)
s.erase(*it);
q[i][1]++;
}
} else {
cout <<"query" << i+1 <<": " << (sum_q(q[i][2]) - sum_q(q[i][1] - 1)) << endl;
}
}
return 0;
} ผลลัพธ์
query1: 14 query3: 10 query4: 7
บทสรุป
ในบทช่วยสอนนี้ เราได้พูดถึงคิวรีผลรวมของช่วงและคิวรีการอัปเดตช่วงสำหรับอาร์เรย์ เราได้พูดคุยถึงแนวทางง่ายๆ ในการแก้ปัญหานี้และแนวทางที่มีประสิทธิภาพโดยใช้ Binary Indexed Tree เรายังพูดถึงโปรแกรม C++ สำหรับปัญหานี้ ซึ่งเราสามารถทำได้ด้วยภาษาโปรแกรม เช่น C, Java, Python เป็นต้น เราหวังว่าคุณจะพบว่าบทช่วยสอนนี้มีประโยชน์