题意:
求一个子矩阵要求其矩阵内的合最大。
题解:
正常的求最大子矩阵的复杂度是O(n^3)
对于这一题说复杂度过不去,注意到这个题总共只有2000个点关键点在与这里优化
最大子矩阵可以压缩矩阵变成最大字段和问题
然后可以通过带修改的最大字段和维护这2000个点,复杂度就变成了了O(n^2logn)
将算出每一列的合的操作 用待修改的最大字段和的线段树维护。
1 #include <cstdio> 2 #include <cstring> 3 #include <queue> 4 #include <cmath> 5 #include <algorithm> 6 #include <set> 7 #include <iostream> 8 #include <map> 9 #include <stack> 10 #include <string> 11 #include <vector> 12 #define pi acos(-1.0) 13 #define eps 1e-9 14 #define fi first 15 #define se second 16 #define rtl rt<<1 17 #define rtr rt<<1|1 18 #define bug printf("******\n") 19 #define mem(a,b) memset(a,b,sizeof(a)) 20 #define name2str(x) #x 21 #define fuck(x) cout<<#x" = "<<x<<endl 22 #define f(a) a*a 23 #define sf(n) scanf("%d", &n) 24 #define sff(a,b) scanf("%d %d", &a, &b) 25 #define sfff(a,b,c) scanf("%d %d %d", &a, &b, &c) 26 #define sffff(a,b,c,d) scanf("%d %d %d %d", &a, &b, &c, &d) 27 #define pf printf 28 #define FRE(i,a,b) for(i = a; i <= b; i++) 29 #define FREE(i,a,b) for(i = a; i >= b; i--) 30 #define FRL(i,a,b) for(i = a; i < b; i++)+ 31 #define FRLL(i,a,b) for(i = a; i > b; i--) 32 #define FIN freopen("data.txt","r",stdin) 33 #define gcd(a,b) __gcd(a,b) 34 #define lowbit(x) x&-x 35 #define rep(i,a,b) for(int i=a;i<b;++i) 36 #define per(i,a,b) for(int i=a-1;i>=b;--i) 37 using namespace std; 38 typedef long long LL; 39 typedef unsigned long long ULL; 40 const int maxn = 4000 + 7; 41 const int maxm = 8e6 + 10; 42 const int mod = 1e9 + 7; 43 const int INF = 0x3f3f3f3f; 44 int T, n; 45 LL s[maxn], x[maxn], y[maxn], a[maxn], b[maxn], w[maxn], mp[maxn][maxn]; 46 struct Segtree { 47 LL maxx, vl, vr, sum, fg; 48 49 } Tree[maxn << 3]; 50 void updata ( int rt ) { 51 Tree[rt].maxx = max ( Tree[rtl].maxx, max ( Tree[rtr].maxx, Tree[rtl].vr + Tree[rtr].vl ) ); 52 Tree[rt].sum = Tree[rtl].sum + Tree[rtr].sum; 53 Tree[rt].vl = max ( Tree[rtl].vl, Tree[rtl].sum + Tree[rtr].vl ); 54 Tree[rt].vr = max ( Tree[rtr].vr, Tree[rtr].sum + Tree[rtl].vr ); 55 } 56 void build ( int l, int r, int rt ) { 57 Tree[rt].fg = true; 58 if ( l == r ) { 59 Tree[rt].sum = s[l]; 60 Tree[rt].maxx = s[l]; 61 Tree[rt].vl = s[l]; 62 Tree[rt].vr = s[l]; 63 return ; 64 } 65 int mid = ( l + r ) >> 1; 66 build ( l, mid, rtl ); 67 build ( mid + 1, r, rtr ); 68 updata ( rt ); 69 } 70 void add ( int l, int r, int rt, int pos, int to ) { 71 if ( l > pos || r < pos ) return ; 72 if ( l == r ) { 73 Tree[rt].sum += to; 74 Tree[rt].maxx += to; 75 Tree[rt].vl += to; 76 Tree[rt].vr += to; 77 return ; 78 } 79 int mid = ( l + r ) >> 1; 80 add ( l, mid, rtl, pos, to ); 81 add ( mid + 1, r, rtr, pos, to ); 82 updata ( rt ); 83 } 84 Segtree query ( int l, int r, int rt, int sa, int se ) { 85 if ( sa <= l && r <= se ) return Tree[rt]; 86 int mid = ( l + r ) >> 1; 87 if ( sa > mid ) return query ( mid + 1, r, rtr, sa, se ); 88 if ( se <= mid ) return query ( l, mid, rtl, sa, se ); 89 Segtree t, lson, rson; 90 lson = query ( l, mid, rtl, sa, se ); 91 rson = query ( mid + 1, r, rtr, sa, se ); 92 t.vl = max ( lson.vl, lson.sum + rson.vl ); 93 t.vr = max ( rson.vr, lson.vr + rson.sum ); 94 t.maxx = max ( lson.vr + rson.vl, max ( lson.maxx, rson.maxx ) ); 95 return t; 96 } 97 vector<LL>v[maxn]; 98 int main() { 99 // FIN; 100 sf ( T ); 101 while ( T-- ) { 102 sf ( n ); 103 for ( int i = 1 ; i <= n ; i++ ) { 104 scanf ( "%lld%lld%lld", &x[i], &y[i], &w[i] ); 105 a[i] = x[i], b[i] = y[i]; 106 v[i].clear(); 107 } 108 sort ( a + 1, a + 1 + n ), sort ( b + 1, b + 1 + n ); 109 int len1 = unique ( a + 1, a + 1 + n ) - a - 1; 110 int len2 = unique ( b + 1, b + 1 + n ) - b - 1; 111 for ( int i = 0 ; i <= n ; i++ ) for ( int j = 0 ; j <= n ; j++ ) mp[i][j] = 0; 112 for ( int i = 1 ; i <= n ; i++ ) { 113 x[i] = lower_bound ( a + 1, a + 1 + len1, x[i] ) - a; 114 y[i] = lower_bound ( b + 1, b + 1 + len2, y[i] ) - b; 115 mp[y[i]][x[i]] += w[i]; 116 } 117 for ( int i = 1 ; i <= n ; i++ ) 118 for ( int j = 1 ; j <= n ; j++ ) 119 if ( mp[i][j] ) v[i].push_back ( j ); 120 LL ans = 0; 121 for ( int i = 1 ; i <= n ; i++ ) { 122 for ( int j = 1 ; j <= n ; j++ ) s[j] = mp[i][j]; 123 build ( 1, n, 1 ); 124 ans = max ( ans, query ( 1, n, 1, 1, n ).maxx ); 125 for ( int j = i + 1 ; j <= n ; j++ ) { 126 for ( int k = 0 ; k < v[j].size() ; k++ ) { 127 add ( 1, n, 1, v[j][k], mp[j][v[j][k]] ); 128 } 129 ans = max ( ans, query ( 1, n, 1, 1, n ).maxx ); 130 } 131 } 132 printf ( "%lld\n", ans ); 133 } 134 return 0; 135 }