Sparse Table是一種資料結構,在
給一個數列
10
3 2 4 5 6 8 1 2 9 7
7
1 5
3 5
1 10
5 8
6 6
2 4
2 9
6
6
9
8
8
5
9
dp[i][j] = max(dp[i - 1][j], dp[i - 1][j + (1 << (i - 1))])
我在一開始寫的時候忘記給
#include <bits/stdc++.h>
#define IOS ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int N = 5e5 + 5;
int n, m, arr[N], dp[35][N];
void sparse_table(int n){
for(int i = 1;i <= 31;i++){
for(int j = 0;(j + (1LL << (i - 1))) < n;j++){
dp[i][j] = max(dp[i - 1][j], dp[i - 1][j + (1LL << (i - 1))]);
}
}
}
int query(int l, int r){
int idx = __lg(r - l + 1);
return max(dp[idx][l], dp[idx][r - (1LL << idx) + 1]);
}
int main(){
IOS
cin >> n;
for(int i = 0;i < n;i++) cin >> arr[i];
cin >> m;
for(int i = 0;i < n;i++) dp[0][i] = arr[i];
sparse_table(n);
while(m--){
int l, r;
cin >> l >> r;
if(l > r) swap(l, r);
l--, r--;
cout << query(l, r) << '\n';
}
return 0;
}
我這一題也用過線段樹來寫過,速度上差不多,線段樹是
#include <bits/stdc++.h>
#define IOS ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define L(x) (x << 1)
#define R(x) ((x << 1) | 1)
using namespace std;
typedef long long ll;
int n, m;
ll seg[500005 << 2];
struct Node{
int left, right;
int tag;
int value;
};
ll pull(int x){
return seg[x] = max(seg[L(x)], seg[R(x)]);
}
void build(int x, int l, int r){
if(l == r){
cin >> seg[x];
return;
}
int mid = (l + r) >> 1;
build(L(x), l, mid);
build(R(x), mid + 1, r);
pull(x);
}
void update(int x, int l, int r, int pos, int val){
if(l == r){
seg[x] += val;
return;
}
int mid = (l + r) >> 1;
if(pos >= mid) update(L(x), l, mid, pos, val);
else update(R(x), mid + 1, r, pos, val);
pull(x);
}
ll query(int x, int l, int r, int ql, int qr){
if(ql <= l && qr >= r)
return seg[x];
ll ret = 0;
int mid = (l + r) >> 1;
if(qr <= mid) return query(L(x), l, mid, ql, qr);
else if(ql > mid) return query(R(x), mid + 1, r, ql, qr);
return max(query(L(x), l, mid, ql, mid), query(R(x), mid + 1, r, mid + 1, qr));
}
int main(){
IOS
cin >> n;
build(1, 1, n);
cin >> m;
while(m--){
int l, r;
cin >> l >> r;
if(l > r) swap(l, r);
cout << query(1, 1, n, l, r) << '\n';
}
return 0;
}
這題我也有用分塊算法寫寫看,但是只拿60%,剩下的TLE了。
再來這一題會有點變化,我自己看了解答之後還是寫了很久才做出來。
Difference Array
D[i] = k1 * m
D[i+1] = k2 * m
...
D[j-1] = kn * m
#include <bits/stdc++.h>
#define IOS ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define INF 0x3f3f3f3f
#define int long long
using namespace std;
typedef long long ll;
const int N = 2e5 + 5;
int t, arr[N], dp[31][N];
int gcd(int a, int b){
if(b == 0) return a;
return gcd(b, a % b);
}
void sparse_table(int n){
for(int i = 1;i <= 31;i++){
for(int j = 0;(j + (1LL << (i - 1))) < n - 1;j++){
if(j + (1LL << i) - 1 < n - 1)
dp[i][j] = gcd(dp[i - 1][j], dp[i - 1][j + (1LL << (i - 1))]);
}
}
}
int query(int l, int r){
int idx = __lg(r - l + 1);
return gcd(dp[idx][l], dp[idx][r - (1LL << idx) + 1]);
}
signed main(){
IOS
cin >> t;
while(t--){
int n;
cin >> n;
for(int i = 0;i < n;i++) cin >> arr[i];
if(n == 1){
cout << 1 << '\n';
continue;
}
int ans = 1, left = 0, right = 1;
for(int i = 1;i < n;i++){
dp[0][i - 1] = abs(arr[i] - arr[i - 1]);
}
sparse_table(n);
for(int right = 0;right < n - 1;right++){
while(left < right && query(left, right) == 1) left++;
if(query(left, right) > 1) ans = max(ans, right - left + 2);
}
cout << ans << '\n';
}
return 0;
}
這題也能用線段樹,但我就懶得寫了,我自己覺得這題的想法很難想到,真的很神奇,同時我也覺得能想到倍增法的人也好厲害,整個過程都非常漂亮,真的很驚豔,那這一篇sparse table就寫到這了,話說我還沒用過sparse table寫過區間和的問題,改天來寫寫看!