2024杭电多校4L 寻找宝藏
设$f_i$表示从左上角到i节点的最多金币数,$g_i$表示从i节点到右下角的最多金币数(即最大加权不下降子序列)
一个矩阵限制了一定区间不能走,同时也规定了只能通过如下四种方法走过来
蓝色表示障碍矩阵,要么在绿色矩阵中选择一个节点x,经过绿色区域一定会避开蓝色矩阵
要么从上方的红色区间选择一个点,然后从右方的红色区间选择一个点,这样也可以避开蓝色矩阵
同理
选择从下方过来如上,依旧有两种情况
先用树状数组求出$f_i,g_i$,然后再用树状数组求出前缀区间或者后缀区间最大值即可
CODE:
1 #include<bits/stdc++.h> 2 #define rep(i,a,b) for(int i=a;i<=b;i++) 3 #define dwn(i,a,b) for(int i=a;i>=b;i--) 4 #define lowbit(x) (x&(-x)) 5 #define MAXN 302501 6 #define int long long 7 using namespace std; 8 typedef long long ll; 9 inline int read(){ 10 int x=0,f=1; 11 char ch=getchar(); 12 while(ch>'9' || ch<'0'){if(ch=='-') f=-1; ch=getchar();} 13 while('0'<=ch && ch<='9') x=(x<<1)+(x<<3)+ch-'0',ch=getchar(); 14 return x*f; 15 } 16 int n,m; 17 struct node{ 18 int u, ur, r, d, l, dl; 19 }t[MAXN]; 20 int p[MAXN],v[MAXN],c[MAXN],N; 21 int f[MAXN],g[MAXN],h[MAXN],ans[MAXN]; 22 struct e{ 23 int yl, yr; 24 }q[MAXN]; 25 vector<int> ql[MAXN],qr[MAXN]; 26 void clr(){ 27 rep(i,1,n) ql[i].clear(), qr[i].clear(); 28 } 29 int get(int x){ 30 return n - x + 1; 31 } 32 void ins(int x,int y){ 33 while(x <= n) c[x] = max(c[x], y), x += lowbit(x); 34 } 35 int qry(int x){ 36 int res = 0; 37 while(x) res = max(res, c[x]), x -= lowbit(x); 38 return res; 39 } 40 void wk(){ 41 n = read(); m = read(); 42 rep(i,1,n) p[i] = read(),v[i] = read(); 43 rep(i,1,m){ 44 int xl,xr; 45 xl = read(); q[i].yl = read(); 46 xr = read(); q[i].yr = read(); 47 ql[xl].emplace_back(i); qr[xr].emplace_back(i); 48 } 49 rep(i,0,n) c[i] = 0; 50 rep(i,1,n){ 51 for(auto j : ql[i]) t[j].l = qry(q[j].yr); 52 f[i] = qry(p[i]) + v[i]; 53 ins(p[i],f[i]); 54 for(auto j : qr[i]) t[j].u = qry(q[j].yl - 1); 55 } 56 rep(i,0,n) c[i] = 0; 57 dwn(i,n,1){ 58 for(auto j : qr[i]) t[j].r = qry(get(q[j].yl)); 59 g[i] = qry(get(p[i])) + v[i]; 60 ins(get(p[i]),g[i]); 61 for(auto j : ql[i]) t[j].d = qry(get(q[j].yr + 1)); 62 } 63 rep(i,1,n) h[i] = g[i] + f[i] - v[i]; 64 rep(i,0,n) c[i] = 0; 65 rep(i,1,n){ 66 for(auto j : ql[i]) t[j].dl = qry(get(q[j].yr + 1)); 67 ins(get(p[i]),h[i]); 68 } 69 rep(i,0,n) c[i] = 0; 70 dwn(i,n,1){ 71 for(auto j : qr[i]) t[j].ur = qry(q[j].yl - 1); 72 ins(p[i],h[i]); 73 } 74 rep(j,1,m) ans[j] = max(max(t[j].dl, t[j].d + t[j].l), max(t[j].ur, t[j].u + t[j].r)); 75 rep(i,1,m) printf("%lld\n",ans[i]); 76 } 77 signed main(){ 78 int T = read(); 79 while(T--){ 80 clr(); 81 wk(); 82 } 83 return 0; 84 }