这道题,由于细节不注意,挂了,另一方面,也是由于对线段树的理解不够透彻,线段树是将一个个的大区间分层一个一个的小区间,而这个大区间很可能会跨越很多很多小区间,但是这个大区间的很多值都与小区间有关,而不是相同,例如最值的差,举个例子:
区间[1,8]分为区间[1,4](区间1)[5,8])(区间2),其中区间1的最值分别为 4,8;区间2的最值分别为2,1;那么如果直接分开求(分别为4,1),在比大小,得出总区间的最值得差为4,而实际上是8 - 1 = 7;
这就是下面这个代码错误的原因
#include<bits/stdc++.h>
using namespace std;
const int maxxn = 180000 * 4 + 20;
const int maxx = 180010;
int n,qq;
int a[maxx];
struct node {
int l,r,dat,mn;
};
node t[maxxn];
inline int Read () {
int xx = 0;
int ff = 1;
char ch = getchar();
while (ch > '9' || ch < '0') {
if (ch == '-') ff = -1;
ch = getchar();
}
while (ch <= '9' && ch >= '0') {
xx = (xx << 1) + (xx << 3) + (ch ^ 48);
ch = getchar();
}
return xx * ff;
}
inline void WW (int x) {
if (x == 0) {
putchar('0');
putchar(10);
return ;
}
if (x < 0) {
putchar('-');
x = -x;
}
int num = 0;
char ch[19];
while (x != 0) {
ch[++num] = (x % 10) + '0';
x /= 10;
}
while (num != 0) {
putchar(ch[num--]);
}
putchar(10);
return ;
}
void build (int p,int l,int r) {
t[p].l = l; t[p].r = r;
if (l == r) {
t[p].dat = a[l];
t[p].mn = a[l];
return ;
}
int mid = l + r >> 1;
build(p << 1,l,mid);
build(p << 1 | 1,mid + 1,r);
t[p].dat = max(t[p << 1].dat,t[p << 1 | 1].dat);
t[p].mn = min(t[p << 1].mn,t[p << 1 | 1].mn);
return ;
}
inline int ass (int p,int l,int r) {
if (t[p].l >= l && t[p].r <= r) {
return (t[p].dat - t[p].mn);//这里是两个分区间的最值的差,而不是整个区间的
}
int mid = t[p].l + t[p].r >> 1;
int ans = -99999;
if (l <= mid) ans = max(ans,ass(p << 1,l,r));
if (r > mid) ans = max(ans,ass(p << 1 | 1,l,r));
return ans;
}
int main () {
n = Read(); qq = Read();
for (int i = 1;i <= n;i++) {
a[i] = Read();
}
build(1,1,n);
for (int i = 1;i <= qq;i++) {
int aa = Read(); int bb = Read();
WW(ass(1,aa,bb));
}
return 0;
}
正解
#include<bits/stdc++.h>
using namespace std;
const int maxxn = 180000 * 4 + 20;
const int maxx = 180010;
int n,qq;
int a[maxx];
struct node {
int l,r,dat,mn;
};
node t[maxxn];
inline int Read () {
int xx = 0;
int ff = 1;
char ch = getchar();
while (ch > '9' || ch < '0') {
if (ch == '-') ff = -1;
ch = getchar();
}
while (ch <= '9' && ch >= '0') {
xx = (xx << 1) + (xx << 3) + (ch ^ 48);
ch = getchar();
}
return xx * ff;
}
inline void WW (int x) {
if (x == 0) {
putchar('0');
putchar(10);
return ;
}
if (x < 0) {
putchar('-');
x = -x;
}
int num = 0;
char ch[19];
while (x != 0) {
ch[++num] = (x % 10) + '0';
x /= 10;
}
while (num != 0) {
putchar(ch[num--]);
}
putchar(10);
return ;
}
void build (int p,int l,int r) {
t[p].l = l; t[p].r = r;
if (l == r) {
t[p].dat = a[l];
t[p].mn = a[l];
return ;
}
int mid = l + r >> 1;
build(p << 1,l,mid);
build(p << 1 | 1,mid + 1,r);
t[p].dat = max(t[p << 1].dat,t[p << 1 | 1].dat);
t[p].mn = min(t[p << 1].mn,t[p << 1 | 1].mn);
return ;
}
inline int ass1 (int p,int l,int r) {
if (t[p].l >= l && t[p].r <= r) {
return t[p].dat;
}
int mid = t[p].l + t[p].r >> 1;
int ans = -99999;
if (l <= mid) ans = max(ans,ass1(p << 1,l,r));
if (r > mid) ans = max(ans,ass1(p << 1 | 1,l,r));
return ans;
}
inline int ass2 (int p,int l,int r) {
if (t[p].l >= l && t[p].r <= r) {
return t[p].mn;
}
int mid = t[p].l + t[p].r >> 1;
int ans = 9999999;
if (l <= mid) ans = min(ans,ass2(p << 1,l,r));
if (r > mid) ans = min(ans,ass2(p << 1 | 1,l,r));
return ans;
}
int main () {
n = Read(); qq = Read();
for (int i = 1;i <= n;i++) {
a[i] = Read();
}
build(1,1,n);
for (int i = 1;i <= qq;i++) {
int aa = Read(); int bb = Read();
WW(ass1(1,aa,bb) - ass2(1,aa,bb));
}
return 0;
}