安利系列博文
https://www.cnblogs.com/tyner/p/11565348.html
https://www.cnblogs.com/tyner/p/11605073.html
做个小总结
树状数组二维数点的特征:
- 矩阵(假设x轴从左到右,y轴从下到上)
- 是树状数组可以维护的
能用树状数组的要求 :
- 维护的东西要有前缀性(说人话:比如我们平常用它来维护的前缀和,就有前缀性
(这不是废话么, - 如果是求任意区间的信息,它要有可减性(因为我们是运用前缀性求得的任意区间)(说人话:我们求区间[l,r]的和,用[1, r]减去[1, l-1]的信息即可
https://www.luogu.org/problem/P3431
可是这题是要维护的是max
, 即二维数max
,这max
和min
一样,都木有可减性
所以树状数组本来是不支持修改和维护max(min)的
但这题的每次修改都只会使原值越来越大(越来越小),所以才可以套用,来维护max(min)
(要是可以改得比原值小,显然就不能用树状数组维护了
(但这个貌似也是只能维护左端点为1的最值。。。
#include<cstdio>
#include<algorithm>
using namespace std;
int read() {
char ch = getchar(); int f=1, x=0;
while(ch<'0' || ch>'9') {if(ch=='-') f=-1; ch = getchar();}
while(ch>='0' && ch<='9') {x = x*10+ch-'0'; ch = getchar();}
return x*f;
}
const int MAX = 100000+99;
#define lowbit(x) (x&-x)
int n,m,k;
int tot;
long long t[MAX];
long long f[MAX];//f[i]:第i个车站的最大载人数,则f[i] = max(f[j]) + v[i], a[j].x∈[1, a[i].x]//注意可以等于a[i].x
struct node{
int xx, x, y, v;
}a[MAX];
bool cmp1(node a, node bb) {
return a.xx < bb.xx;
}
bool cmp2(node a, node bb) {
return (a.y<bb.y) || (a.y==bb.y && a.x<bb.x);
}
long long query(int x) {
long long mx = 0;
while(x) mx=max(mx, t[x]), x-=lowbit(x);//.........
return mx;
}
void add(int x, long long v) {//单点修改
while(x <= tot) t[x] = max(t[x], v), x+=lowbit(x);//.....想想树状数组的结构
}
int main() {
n=read(), m=read(), k=read();
for(int i = 1; i <= k; i++) a[i].xx=read(), a[i].y=read(), a[i].v=read();
sort(a+1, a+1+k, cmp1);
tot = 1;
a[1].x = 1;
for(int i = 2; i <= k; i++) {
if(a[i].xx != a[i-1].xx) ++tot;
a[i].x = tot;
}
sort(a+1, a+1+k, cmp2);
for(int i = 1; i <= k; i++) {
f[i] = query(a[i].x) + a[i].v;
add(a[i].x, f[i]);
}
printf("%lld
", query(tot));//注意,这还要更新 x = tot直线
}