安利系列博文

https://www.cnblogs.com/tyner/p/11565348.html

https://www.cnblogs.com/tyner/p/11605073.html

做个小总结

树状数组二维数点的特征

  1. 矩阵(假设x轴从左到右,y轴从下到上)
  2. 是树状数组可以维护的

能用树状数组的要求 :

  1. 维护的东西要有前缀性(说人话:比如我们平常用它来维护的前缀和,就有前缀性,
  2. 如果是求任意区间的信息,它要有可减性(因为我们是运用前缀性求得的任意区间)(说人话:我们求区间[l,r]的和,用[1, r]减去[1, l-1]的信息即可

https://www.luogu.org/problem/P3431

可是这题是要维护的是max, 即二维数max,这maxmin一样,都木有可减性

所以树状数组本来是不支持修改和维护max(min)的

但这题的每次修改都只会使原值越来越大(越来越小),所以才可以套用,来维护max(min)

#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\n", query(tot));//注意,这要取全局t最大值
} 
01-22 18:39