传送门

赛时靠spfa求最长路骗了30pts

  • spfa的时间复杂度是\(O(k|E|)\),不是\(O(k|N|)\)!
  • dijkstra 时间复杂度\(O((n+m)logn)\)
  • 特别注意这两个的复杂度都和边数密切相关

spfa的话按a值分层,按层建边即可

正解是个dp,考场上想到dp,但dp思路错了

令\(dp[i][j]\)为在\((i, j)\)位置结束时的最大和

\[dp[i][j] = max(b[i][j]+dp[i'][j']+|i-i'|+|j-j'|)
\]

又一个带绝对值的题,可以分情况讨论

对于一个点\((i, j)\),可以用四个二维树状数组分别维护\(i,j\)为正,负时的最大值,

根据点\((i, j)\)和\((i', j')\)的位置关系查询即可,复杂度\(O(nmlognlogm)\)

但是还有一种\(O(nm)\)的解法:

题面里那个 \(|i-i'|+|j-j'|\) 其实是曼哈顿距离

这里我们要求其最大值

  • 曼哈顿距离在处理绝对值时,常转换为切比雪夫距离以简化计算

考虑转化为切比雪夫距离,那方程可以化为

\[dp[i][j] = b[i][j]+max(dp[i'][j']+max(|i-i'|,|j-j'|))
\]

要求距离尽可能大,所以我们可以维护全局 \(max\ \{dp[i'][j']+i', dp[i'][j']-i', dp[i'][j']+j', dp[i'][j']-j'\}\), 转移时用这个分情况转移

yysy,我因为脑残没仔细看题面a=0的点舍弃从下午3点调到6点

Code:

#include <bits/stdc++.h>
using namespace std;
#define INF 0x7fffffffffff
#define N 2010
#define ll long long
#define ld long double
#define usd unsigned
#define ull unsigned long long
//#define int long long #define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
char buf[1<<21], *p1=buf, *p2=buf;
inline int read() {
int ans=0, f=1; char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
return ans*f;
} int n, m; namespace force{
int tot, pos;
int head[N*N], size, lim[N*N], lcnt; ll dis[N*N];
bool vis[N*N];
int ss, st;
struct point{int a, b, x, y, rk; ll w;}mp[N*N];
inline bool operator < (point a, point b) {return a.a<b.a;}
struct edge{int to, next, val;}e[N*N*3];
inline void add(int s, int t, int w) {edge* k=&e[++size]; k->to=t; k->val=w; k->next=head[s]; head[s]=size;}
void spfa(int s) {
queue<int> q;
dis[s]=0; vis[s]=1; q.push(s);
int t;
while (q.size()) {
t=q.front(); q.pop();
vis[t]=0;
for (int i=head[t],v; i; i=e[i].next) {
v = e[i].to;
//cout<<t<<": "<<dis[t]<<' '<<mp[t].w<<' '<<e[i].val<<' '<<dis[v]<<endl;
if (dis[t]+mp[t].w+e[i].val < dis[v]) {
dis[v] = dis[t]+mp[t].w+e[i].val;
if (!vis[v]) q.push(v);
}
}
}
//cout<<"dis: "; for (int i=1; i<=tot+2; ++i) cout<<dis[i]<<' '; cout<<endl;
}
void solve() {
tot=0; for (int i=1; i<=n; ++i) for (int j=1; j<=m; ++j) mp[++tot].a=read(), mp[tot].x=i, mp[tot].y=j, mp[tot].rk=tot;
tot=0; for (int i=1; i<=n; ++i) for (int j=1; j<=m; ++j) mp[++tot].w=-read();
sort(mp+1, mp+tot+1);
//for (int i=1; i<=tot; ++i) cout<<mp[i].a<<' '; cout<<endl;
for (pos=1; pos<=tot; ++pos) if (mp[pos].a!=mp[pos-1].a) lim[++lcnt]=pos;
lim[++lcnt]=tot+1;
for (int i=1; i<=tot+10; ++i) dis[i]=INF;
ss=tot+1; st=tot+2;
for (int i=lim[1]; i<lim[2]; ++i) add(ss, i, 0); //, cout<<"ss: "<<ss<<' '<<i<<endl;
for (int i=lim[lcnt-1]; i<=tot; ++i) add(i, st, 0); //, cout<<"st: "<<i<<' '<<st<<endl;
for (int i=1; i<lcnt; ++i) {
for (int j=lim[i]; j<lim[i+1]; ++j) {
for (int k=lim[i+1]; k<lim[i+2]; ++k) add(j, k, -(abs(mp[j].x-mp[k].x)+abs(mp[j].y-mp[k].y))); //, cout<<"add "<<j<<' '<<k<<' '<<-(abs(mp[j].x-mp[k].x)+abs(mp[j].y-mp[k].y))<<endl;
}
}
spfa(ss);
printf("%lld\n", -dis[st]);
}
} namespace task{
// 0->i 1->-i 2->j 3->-j
int tot, lcnt, pos[4], pos2;
ll maxn[4], dp[N*N], ans;
struct point{int a, i, j; ll b;}p[N*N];
inline bool operator < (point a, point b) {return a.a<b.a;}
struct line{int l, r; inline void build(int l_, int r_) {l=l_; r=r_;}}lin[N*N];
void solve() {
memset(maxn, 128, sizeof(maxn));
tot=0; for (int i=1; i<=n; ++i) for (int j=1; j<=m; ++j) p[++tot].a=read(), p[tot].i=i+j, p[tot].j=i-j;
tot=0; for (int i=1; i<=n; ++i) for (int j=1; j<=m; ++j) p[++tot].b=read();
sort(p+1, p+tot+1);
for (pos2=1; !p[pos2].a; ++pos2) ;
for (int i=pos2; i<=tot; ++i) {
lin[++lcnt].l=i;
for (int j=i+1; j<=tot&&(p[j].a==p[j-1].a); ++i,++j) ;
lin[lcnt].r=i;
}
//for (int i=1; i<=lcnt; ++i) cout<<lin[i].l<<","<<lin[i].r<<endl;
//for (int i=1; i<=tot; ++i) cout<<p[i].i<<' '<<p[i].j<<endl;
int i1, j1;
for (int j=lin[1].l; j<=lin[1].r; ++j) {
i1=p[j].i, j1=p[j].j;
dp[j] = p[j].b;
ans = max(ans, dp[j]);
}
for (int j=lin[1].l; j<=lin[1].r; ++j) {
i1=p[j].i, j1=p[j].j;
//cout<<"ij: "<<i1<<' '<<j1<<endl;
maxn[0] = max(maxn[0], dp[j]+i1);
maxn[1] = max(maxn[1], dp[j]-i1);
maxn[2] = max(maxn[2], dp[j]+j1);
maxn[3] = max(maxn[3], dp[j]-j1);
}
//cout<<"ans: "<<ans<<endl;
//cout<<"maxn: "; for (int i=0; i<4; ++i) cout<<maxn[i]<<' '; cout<<endl;
for (int i=2; i<=lcnt; ++i) {
for (int j=lin[i].l; j<=lin[i].r; ++j) {
i1=p[j].i, j1=p[j].j;
dp[j] = p[j].b+max(max(max(maxn[0]-i1, maxn[1]+i1), maxn[2]-j1), maxn[3]+j1);
//cout<<"ans in "<<maxn[0]-i1<<' '<<maxn[1]+i1<<' '<<maxn[2]-j1<<' '<<maxn[3]+j1<<endl;
ans = max(ans, dp[j]);
}
for (int j=lin[i].l; j<=lin[i].r; ++j) {
i1=p[j].i, j1=p[j].j;
maxn[0] = max(maxn[0], dp[j]+i1);
maxn[1] = max(maxn[1], dp[j]-i1);
maxn[2] = max(maxn[2], dp[j]+j1);
maxn[3] = max(maxn[3], dp[j]-j1);
}
//cout<<"ans: "<<ans<<endl;
//cout<<"maxn: "; for (int i=0; i<4; ++i) cout<<maxn[i]<<' '; cout<<endl;
}
printf("%lld\n", ans);
}
} signed main()
{
#ifdef DEBUG
freopen("1.in", "r", stdin);
#endif n=read(); m=read();
task::solve(); return 0;
}

题解 biology的更多相关文章

  1. HDU 5590 ZYB's Biology 水题

    ZYB's Biology Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid ...

  2. HDU1560 DNA sequence(IDA*)题解

    DNA sequence Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) To ...

  3. Biology(湖南集训)

    题目大意:n个字符串,m个操作,可以插入字符串,也可以询问某T个字符串的最长后缀 题解:Trie+lca Trie树的插入与查询操作.把字符串反转就相当于求公共前缀. lca的深度就是公共前缀的长度. ...

  4. 遗传编程(GA,genetic programming)算法初探,以及用遗传编程自动生成符合题解的正则表达式的实践

    1. 遗传编程简介 0x1:什么是遗传编程算法,和传统机器学习算法有什么区别 传统上,我们接触的机器学习算法,都是被设计为解决某一个某一类问题的确定性算法.对于这些机器学习算法来说,唯一的灵活性体现在 ...

  5. 2016 华南师大ACM校赛 SCNUCPC 非官方题解

    我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...

  6. noip2016十连测题解

    以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...

  7. BZOJ-2561-最小生成树 题解(最小割)

    2561: 最小生成树(题解) Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1628  Solved: 786 传送门:http://www.lyd ...

  8. Codeforces Round #353 (Div. 2) ABCDE 题解 python

    Problems     # Name     A Infinite Sequence standard input/output 1 s, 256 MB    x3509 B Restoring P ...

  9. 哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解

    题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练 ...

随机推荐

  1. Pandas高级教程之:window操作

    目录 简介 滚动窗口 Center window Weighted window 加权窗口 扩展窗口 指数加权窗口 简介 在数据统计中,经常需要进行一些范围操作,这些范围我们可以称之为一个window ...

  2. 『动善时』JMeter基础 — 55、使用非GUI模式运行JMeter(命令行模式)

    目录 1.JMeter的非GUI模式说明 2.为什么使用非GUI模式运行JMeter 3.使用非GUI模式运行JMeter (1)非GUI模式运行JMeter步骤 (2)其它参数说明 4.CLI模式运 ...

  3. java课堂考试总结

    9月22日,进行了开学第一堂的java测试,来检验暑假的自学成果.下午的考试中,时间应该是比较充分的,但是我还是有许多功能模块没有完成,功能缺少,在进行测试的时候暴露出了许多漏洞. 总结一下,在暑假的 ...

  4. Spring boot+Mybatis+MySQL插入中文乱码

    转载:https://www.jianshu.com/p/bd0311a33c16 现象: 搭建spring boot+mybatis+mysql时出现插入mysql的中文出现乱码???.   mys ...

  5. Long类型框架自动序列化成String失效问题排查

    目录 问题描述 猜想 1. 写错了 2. 重新使用 验证猜想 1.验证猜想 2.继续猜想 3.再次猜想 4.再次验证 5.疑惑 6.找到原因,解决疑惑 7.解决 问题描述 微服务架构下进行业务模块开发 ...

  6. informix常见问题

    1.中文乱码 https://www.cnblogs.com/equation/p/5545967.html 2.informix创建数据库和用户 https://wenku.baidu.com/vi ...

  7. Spring 框架中都用到了哪些设计模式

    Spring 框架中都用到了哪些设计模式? Spring 框架中使用到了大量的设计模式,下面列举了比较有代表性的: 1.代理模式-在 AOP 和 remoting 中被用的比较多. 2.单例模式:在 ...

  8. 【对线面试官】Kafka基础入门

    <对线面试官>系列目前已经连载33篇啦,这是一个讲人话面试系列 [对线面试官]Java注解 [对线面试官]Java泛型 [对线面试官] Java NIO [对线面试官]Java反射 &am ...

  9. argparse模块基本用法

    argparse模块基本用法 在 python 编写的程序中,我们经常会看到的 argparse 相关代码,而它究竟怎么使用呢?接招! argparse 是一个命令行参数解析模块 现在提出需求,我需要 ...

  10. Intouch/ifix语音报警系统制作(2)

    在我的先前一篇关于语音报警系统制作的文章中,阐述了如何通过标签组来获得@name@的详细内容,以通过这种方式来进行详细的设备故障播报.经过一段时间的试运行,发现使用标签组的方式会产生较大的耦合,(即当 ...