题解 跑步
首先一个 的 DP 是显然的
然后赛时脑子抽了试图单次 或 维护答案变化
事实上可以支持单次
因为单点权值变化量只有 1
所以如果一个点的 DP 值变了那一定和这次修改的变化量相同
发现一个位置的值变不变之和左上有关
所以一次修改在每一行影响的范围 满足 均单调不降
那就可以单调指针+树状数组
(如果单点权值变化量不止 1 就不能这样做了,仍然可以确定有哪些位置的值变了但不知道变了多少)
复杂度
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 2010
#define fir first
#define sec second
#define ll long long
//#define int long long
int n;
int a[N][N];
ll f[N][N];
char op[10];
namespace force{
void recalc() {
ll ans=0;
for (int i=1; i<=n; ++i)
for (int j=1; j<=n; ++j)
ans+=(f[i][j]=max(f[i-1][j], f[i][j-1])+a[i][j]);
printf("%lld\n", ans);
}
void solve() {
recalc();
for (int i=1,x,y; i<=n; ++i) {
scanf("%s%d%d", op, &x, &y);
if (*op=='U') ++a[x][y];
else --a[x][y];
recalc();
}
}
}
namespace task1{
ll ans;
bool vis[N][N];
queue<pair<int, int>> q;
void recalc() {
ans=0;
for (int i=1; i<=n; ++i)
for (int j=1; j<=n; ++j)
ans+=(f[i][j]=max(f[i-1][j], f[i][j-1])+a[i][j]);
}
void bfs(pair<int, int> s) {
q.push(s);
while (q.size()) {
pair<int, int> u=q.front(); q.pop();
int i=u.fir, j=u.sec, t=max(f[i-1][j], f[i][j-1])+a[i][j], x, y;
vis[i][j]=0;
if (t==f[i][j]) continue;
ans=ans-f[i][j]+t; f[i][j]=t;
x=i+1, y=j; if (x<=n && y<=n && !vis[x][y]) q.push({x, y}), vis[x][y]=1;
x=i, y=j+1; if (x<=n && y<=n && !vis[x][y]) q.push({x, y}), vis[x][y]=1;
}
}
void solve() {
recalc();
printf("%lld\n", ans);
for (int i=1,x,y; i<=n; ++i) {
scanf("%s%d%d", op, &x, &y);
if (*op=='U') ++a[x][y];
else --a[x][y];
bfs({x, y});
printf("%lld\n", ans);
}
}
}
namespace task{
ll ans=0;
struct bit{
ll a[N];
inline void upd(int i, int dat) {for (; i<=n; i+=i&-i) a[i]+=dat;}
inline ll query(int i) {ll ans=0; for (; i; i-=i&-i) ans+=a[i]; return ans;}
inline void upd(int l, int r, int dat) {upd(l, dat); upd(r+1, -dat);}
inline ll operator [] (int t) {return query(t);}
}bit[N];
void recalc() {
ans=0;
for (int i=1; i<=n; ++i)
for (int j=1; j<=n; ++j)
ans+=(f[i][j]=max(f[i-1][j], f[i][j-1])+a[i][j]), bit[i].upd(j, j, f[i][j]);
}
void modify(pair<int, int> s, int k) {
int l=s.sec, r=s.sec;
for (int i=s.fir; i<=n; ++i) {
while (l<=n && bit[i][l]==max(bit[i-1][l], bit[i][l-1])+a[i][l]) ++l;
r=max(l, r);
while (r<=n && bit[i][r]!=max(bit[i-1][r], bit[i][r-1]+k)+a[i][r]) ++r;
if (l<=r-1) bit[i].upd(l, r-1, k), ans+=(r-l)*k;
}
}
void solve() {
recalc();
printf("%lld\n", ans);
for (int i=1,x,y; i<=n; ++i) {
scanf("%s%d%d", op, &x, &y);
if (*op=='U') ++a[x][y];
else --a[x][y];
modify({x, y}, *op=='U'?1:-1);
printf("%lld\n", ans);
}
}
}
signed main()
{
freopen("run.in", "r", stdin);
freopen("run.out", "w", stdout);
scanf("%d", &n);
for (int i=1; i<=n; ++i) for (int j=1; j<=n; ++j) scanf("%d", &a[i][j]);
// force::solve();
task::solve();
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通