1. 程式人生 > 實用技巧 >在第9章例9.9和例9.10的基礎上,寫一個函式del,用來刪除動態連結串列中指定的節點

在第9章例9.9和例9.10的基礎上,寫一個函式del,用來刪除動態連結串列中指定的節點

離散化:離散化就是把大範圍的數,對映到一個小範圍,即把無限空間中的有限個體,對映到有限空間中去,以此來提高演算法的時空效率。 例題:求區間和 假定有一個無限長的數軸,數軸上每個座標上的數都是0。

現在,我們首先進行n次操作,每次操作將某一位置x上的數加c。

接下來,進行m次詢問,每個詢問包含兩個整數l和r,你需要求出在區間[l,r]之間的所有數的和。

輸入格式 第一行包含兩個整數n和m。

接下來n行,每行包含兩個整數x和c。

再接下里m行,每行包含兩個整數l和r。

輸出格式 共m行,每行輸出一個詢問中所求的區間內數字和。

資料範圍 −109 ≤ x ≤ 109, 1 ≤ n,m ≤ 105, −109 ≤ l ≤ r ≤ 109, −10000 ≤ c ≤ 10000 輸入樣例: 33 12 36 75 13 46 78 輸出樣例: 8 0 5 思路:看到這道題想到的肯定是利用字首和進行計算,但是如果直接使用字首和的話我們需要開一個數量級為1e9的陣列,這顯然不太可能,而發現n與m最多就訪問1e5次,所以我們用的空間最多數量級也就1e5,所以 n m x 一共用到的空間是3
e5就足夠了,因此我們就把用到的數都通過離散化對映到小範圍中去,再使用字首和。 那麼離散化的方法:首先把所有要離散化的資料都push_back()all陣列中去,然後先排序,再去重,再利用二分來離散化。 排序:
1 sort(alls.begin(), alls.end());

去重:運用erase,unique來去重(經典方法)

1 alls.erase(unique(alls.begin(), alls.end()), alls.end());

unique的去重原理是將所用不重複的元素放到前邊,將重複的元素放到陣列後邊,最後將迭代器指向最後不重複下標並返回,所以這個操作完美去重。

離散化:即運用二分,也可直接用low_bound,把數插入到a陣列中去。

二分寫法:因為是用到字首和,所以我們的下標從1開始,返回的是r+1

 1 int find(int x)
 2 {
 3     int l = 0, r = alls.size()-1;
 4     while(l < r)
 5     {
 6         int mid = l+r >> 1; 
 7         if(alls[mid] >= x) r = mid;  //依據的是原先數字在alls陣列中的相對位置
 8         else l = mid+1;
 9     }
10 11 return r+1; 12 }

low_bound()寫法:

1 int find(int x) //lower_bound二分寫法
2 {
3     return lower_bound(alls.begin(), alls.end(), x) - alls.begin() + 1;
4 }

總程式碼

 1 #include <iostream>
 2 #include <vector>
 3 #include <algorithm>
 4 
 5 using namespace std;
 6 
 7 typedef pair<int, int> PII;
 8 
 9 const int N = 300010;
10 int n, m;
11 int a[N], s[N];  //a存放離散化後的序列
12 
13 vector<int> alls;  //要散化的所有資料
14 vector<PII> add, query;  //add是存x+c的  query用來存區間兩邊
15 
16 int find(int x)
17 {
18     int l = 0, r = alls.size()-1;
19     while(l < r)
20     {
21         int mid = l+r >> 1; 
22         if(alls[mid] >= x) r = mid;  //依據的是原先數字在alls陣列中的相對位置
23         else l = mid+1;
24     }
25 
26     return r+1;
27 }
28 
29 int main()
30 {
31     cin >> n >> m;
32     for(int i = 0; i < n; i++)
33     {
34         int x, c;
35         cin >> x >> c;
36         add.push_back({x, c});  //在某個數上加c
37 
38         alls.push_back(x);
39     }
40 
41     for(int i = 0; i < m; i++)
42     {
43         int l, r;
44         cin >> l >> r;
45         query.push_back({l, r});
46 
47         alls.push_back(l);
48         alls.push_back(r);
49     }
50 
51     //去重
52     sort(alls.begin(), alls.end());
53     alls.erase(unique(alls.begin(), alls.end()), alls.end());
54 
55     //處理插入
56     for(auto item : add)
57     {
58         int x = find(item.first);
59         a[x] += item.second;
60     }
61 
62     //預處理字首和
63     for(int i = 1; i <= alls.size(); i++) s[i] = s[i-1] + a[i];
64 
65     //處理詢問
66     for(auto item : query)
67     {
68         int l = find(item.first), r = find(item.second);
69         cout << s[r] - s[l-1] << endl;
70     }
71     system("pause");
72     return 0;
73 }