安利系列博文
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)
#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最大值 }