题意:
一个 \(n*n\) 矩阵 \(A\) ,有 \(m_1\) 个操作:给 \(x_1\;x_2\;y_1\;y_2\;w\) ,对所有\(A_{ij}\) (\(i\in[x_1,x_2]\) 且 \(j\in[y_1,y_2]\) )加上 \(w\) ;
有 \(m_2\) 个询问:给 \(x_1\;x_2\;y_1\;y_2\) ,求出\(A_{ij}\) (\(i\in[x_1,x_2]\) 且 \(j\in[y_1,y_2]\) )的最大值。
输入:
第 \(1\) 行 \(3\) 个整数 \(n\;m_1\;m_2\) ( \(1≤n≤2000,1≤m_1≤5*10^4,1≤m_2≤5*10^5\) );
之后 \(m_1\) 行,每行 \(5\) 个整数:\(x_1\;x_2\;y_1\;y_2\;w\) ( \(1≤x_1≤x_2≤n,1≤y_1≤y_2≤n,1≤w≤10^9\) );
之后 \(m_2\) 行,每行 \(4\) 个整数:\(x_1\;x_2\;y_1\;y_2\) ( \(1≤x_1≤x_2≤n,1≤y_1≤y_2≤n\) );
输出:
输出m2行,每行一个整数
官方题解:
n小,所以可以用 \(O(n^2)\)计算出矩阵。然后可以用二维线段树求最值。
个人积累:
【一开始用树状数组求矩阵,明明都是二维差分的思路,我却没想到用二维差分直接 \(O(n^2)\) 求矩阵....
【练习不足o(︶︿︶)o
【然后因为这个树状数组建了四个 \(c[maxn][maxn]\) \(MLE\) ,原本以为线段树 \(tr[maxn<<2][maxn<<2]\) 才可能 \(MLE\) 来着。。结果并不
因为是确定了矩阵A的具体的值,所以线段树无需修改,只需要静态求最值,所以简单多了;
至于二维的建法:以 \(x\) 轴为外部,对每个具体的 \(x_i\),对 \(y\) 轴去建它的子树 \(sg[K].build(1,1,n)\) ;
然后! 当 \(sg[K]\) 每得到一个 \(sg[K].ma[k]\) 时,\(up\) 回去,就是 \(sg[K>>1].ma[k]=max(sg[K>>1].ma[k],sg[K].ma[k])\) ;
这样就建好了!
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=2e3+5; const int inf=0x3f3f3f3f; ll a[maxn][maxn]; int n; ll ma[maxn<<1][maxn<<1]; struct SG1{ void up(int K,int k) { ma[K>>1][k]=max(ma[K>>1][k],ma[K][k]); if(K>>1)up(K>>1,k); } void build(int K,int k,int l,int r,int y) { if(l==r) { ma[K][k]=a[l][y]; up(K,k); return; } int mid=(l+r)>>1; build(K,k<<1,l,mid,y);build(K,k<<1|1,mid+1,r,y); ma[K][k]=max(ma[K][k<<1],ma[K][k<<1|1]); up(K,k); } ll query(int K,int k,int l,int r,int tl,int tr) { if(tl<=l&&r<=tr)return ma[K][k]; int mid=(l+r)>>1; ll res=0; if(tl<=mid)res=query(K,k<<1,l,mid,tl,tr); if(tr>mid&&res<ma[K][k<<1|1])res=max(res,query(K,k<<1|1,mid+1,r,tl,tr)); return res; } }sg; inline void build(int k,int l,int r) { if(l==r) { sg.build(k,1,1,n,l); return; } int mid=(l+r)>>1; build(k<<1,l,mid);build(k<<1|1,mid+1,r); } inline ll query(int k,int l,int r,int x1,int y1,int x2,int y2) { if(y1<=l&&r<=y2)return sg.query(k,1,1,n,x1,x2); int mid=(l+r)>>1; ll res=0; if(y1<=mid)res=query(k<<1,l,mid,x1,y1,x2,y2); if(y2>mid&&res<ma[k<<1|1][1])res=max(res,query(k<<1|1,mid+1,r,x1,y1,x2,y2)); return res; } int main() { int m1,m2,x1,y1,x2,y2,w; scanf("%d%d%d",&n,&m1,&m2); while(m1--) { scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&w); a[x1][y1]+=w;a[x2+1][y2+1]+=w; a[x1][y2+1]-=w;a[x2+1][y1]-=w; } for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) a[i][j]+=a[i-1][j]+a[i][j-1]-a[i-1][j-1]; build(1,1,n); while(m2--) { scanf("%d%d%d%d",&x1,&y1,&x2,&y2); printf("%lld\n",query(1,1,n,x1,y1,x2,y2)); } }
来源:https://www.cnblogs.com/kkkek/p/12247443.html