Codeforces 题目传送门 & 洛谷题目传送门

其实这题本该 2019 年 12 月就 AC 的(详情请见 ycx 发此题题解的时间),然鹅鸽到了现在……

首先以 \(s,t\) 分别为源点跑两遍 dijkstra 是不可避免的,求出 \(s,t\) 到每个点的最短距离 \(d1_i,d2_i\)

其次还可以发现一件事情,那就是对于 \(\forall i,j\),若 \(d1_i<d1_j\) 并且 \(j\) 被选择了,那么 \(i\) 一定被选择了,对于 \(d2_i\) 也可得到类似的性质。换句话说,对于游戏任意一种局面,\(\exist x,y\) 使得恰好只剩下 \(d1_i\geq x\) 且 \(d2_i\geq y\) 的 \(i\) 没有被选择。故考虑以此为状态设计 dp

将 \(d1,d2\) 离散化。设 \(dp_{p,x,y}\) 表示此时轮到 \(p\)(\(0\) 表示先手,\(1\) 表示后手),还剩下 \(d1_i\geq x\) 且 \(d2_i\geq y\) 的点没有被选择,所能得到的最大得分。状态转移方程很容易得到,以 \(p=0\) 为例,显然这一步操作之后留下来的应当是 \(d1_i\geq z\) 且 \(d2_i\geq y\) 的城市,其中 \(z\) 为某个大于 \(x\) 的数,我们不妨枚举 \(z\),记 \(c_{x,y}\) 为 \(d1_i\geq x\) 且 \(d2_i\ge y\) 的城市个数,\(s_{x,y}\) 为 \(d1_i\geq x\) 且 \(d2_i\ge y\) 的城市的权值之和,由于先手要多占领一些城市,故 \(c_{z,y}>c_{x,y}\),故我们有状态转移方程 \(dp_{0,x,y}=s_{x,y}-\min\limits_{c_{z,y}>c_{x,y}}dp_{1,z,y}\),\(dp_{1,x,y}\) 也同理。

容易发现对于某个 \(dp_{p,x,y}\),其决策的集合是一段后缀,故可以预处理 \(nt1_{i,j}\) 表示第一个满足 \(c_{k,j}>c_{i,j}\) 的 \(k\),\(nt2_{i,j}\) 表示 \(c_{i,l}>c_{i,j}\) 的 \(l\),这个预处理复杂度显然是 \(n^2\) 的,处理完之后就可以利用后缀 \(\min\) 进行 \(\mathcal O(1)\) 转移了。

最终先手得分的最大值即为 \(dp_{0,0,0}\),后手得分即为 \(s_{0,0}-dp_{0,0,0}\),比较二者大小即可。

时间复杂度 \(n^2\)。总之此题算 D1D 中较简单的了。

#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define fill0(a) memset(a,0,sizeof(a))
#define fill1(a) memset(a,-1,sizeof(a))
#define fillbig(a) memset(a,63,sizeof(a))
#define pb push_back
#define ppb pop_back
#define mp make_pair
template<typename T1,typename T2> void chkmin(T1 &x,T2 y){if(x>y) x=y;}
template<typename T1,typename T2> void chkmax(T1 &x,T2 y){if(x<y) x=y;}
typedef pair<int,int> pii;
typedef long long ll;
namespace fastio{
#define FILE_SIZE 1<<23
char rbuf[FILE_SIZE],*p1=rbuf,*p2=rbuf,wbuf[FILE_SIZE],*p3=wbuf;
inline char getc(){return p1==p2&&(p2=(p1=rbuf)+fread(rbuf,1,FILE_SIZE,stdin),p1==p2)?-1:*p1++;}
inline void putc(char x){(*p3++=x);}
template<typename T> void read(T &x){
x=0;char c=getchar();T neg=0;
while(!isdigit(c)) neg|=!(c^'-'),c=getchar();
while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=getchar();
if(neg) x=(~x)+1;
}
template<typename T> void recursive_print(T x){if(!x) return;recursive_print(x/10);putc(x%10^48);}
template<typename T> void print(T x){if(!x) putc('0');if(x<0) putc('-'),x=~x+1;recursive_print(x);}
void print_final(){fwrite(wbuf,1,p3-wbuf,stdout);}
}
const int MAXN=2e3;
const int MAXM=1e5;
int n,m,s,t,p[MAXN+5],to[MAXM*2+5],nxt[MAXM*2+5],cst[MAXM*2+5],hd[MAXN+5],ec=0;
void adde(int u,int v,int w){to[++ec]=v;cst[ec]=w;nxt[ec]=hd[u];hd[u]=ec;}
ll d1[MAXN+5],d2[MAXN+5],key1[MAXN+5],key2[MAXN+5],uni1[MAXN+5],uni2[MAXN+5];
int c1[MAXN+5],c2[MAXN+5],num1=0,num2=0,cnt[MAXN+5][MAXN+5];ll sum[MAXN+5][MAXN+5];
ll dp[2][MAXN+5][MAXN+5],mn[2][MAXN+5][MAXN+5];
int nt1[MAXN+5][MAXN+5],nt2[MAXN+5][MAXN+5];
int main(){
scanf("%d%d%d%d",&n,&m,&s,&t);
for(int i=1;i<=n;i++) scanf("%d",&p[i]);
for(int i=1,u,v,w;i<=m;i++){scanf("%d%d%d",&u,&v,&w);adde(u,v,w);adde(v,u,w);}
priority_queue<pair<ll,int>,vector<pair<ll,int> >,greater<pair<ll,int> > > q;
memset(d1,63,sizeof(d1));d1[s]=0;q.push(mp(0,s));
while(!q.empty()){
pii pr=q.top();q.pop();int x=pr.se;
for(int e=hd[x];e;e=nxt[e]){
int y=to[e],z=cst[e];
if(d1[y]>d1[x]+z){
d1[y]=d1[x]+z;
q.push(mp(d1[y],y));
}
}
}
memset(d2,63,sizeof(d2));d2[t]=0;q.push(mp(0,t));
while(!q.empty()){
pii pr=q.top();q.pop();int x=pr.se;
for(int e=hd[x];e;e=nxt[e]){
int y=to[e],z=cst[e];
if(d2[y]>d2[x]+z){
d2[y]=d2[x]+z;
q.push(mp(d2[y],y));
}
}
}
for(int i=1;i<=n;i++) key1[i]=d1[i],key2[i]=d2[i];
sort(key1+1,key1+n+1);sort(key2+1,key2+n+1);key1[0]=key2[0]=-1;
for(int i=1;i<=n;i++){
if(key1[i]!=key1[i-1]) uni1[++num1]=key1[i];
if(key2[i]!=key2[i-1]) uni2[++num2]=key2[i];
}
for(int i=1;i<=n;i++) c1[i]=lower_bound(uni1+1,uni1+num1+1,d1[i])-uni1;
for(int i=1;i<=n;i++) c2[i]=lower_bound(uni2+1,uni2+num2+1,d2[i])-uni2;
// for(int i=1;i<=n;i++) printf("%d %d\n",c1[i],c2[i]);
for(int i=1;i<=n;i++) cnt[c1[i]][c2[i]]++,sum[c1[i]][c2[i]]+=p[i];
for(int i=num1;i;i--) for(int j=num2;j;j--){
cnt[i][j]+=cnt[i+1][j]+cnt[i][j+1]-cnt[i+1][j+1];
sum[i][j]+=sum[i+1][j]+sum[i][j+1]-sum[i+1][j+1];
}
// for(int i=1;i<=num1;i++) for(int j=1;j<=num2;j++)
// printf("%d %d %lld %lld\n",i,j,cnt[i][j],sum[i][j]);
for(int i=num1;i;i--) for(int j=num2;j;j--){
nt1[i][j]=(cnt[i][j]==cnt[i+1][j])?nt1[i+1][j]:(i+1);
nt2[i][j]=(cnt[i][j]==cnt[i][j+1])?nt2[i][j+1]:(j+1);
}
for(int i=num1;i;i--) for(int j=num2;j;j--){
if(!cnt[i][j]) continue;
dp[0][i][j]=sum[i][j]-mn[1][nt1[i][j]][j];
dp[1][i][j]=sum[i][j]-mn[0][i][nt2[i][j]];
// printf("%d %d %d %d\n",i,j,dp[0][i][j],dp[1][i][j]);
mn[0][i][j]=min(mn[0][i][j+1],dp[0][i][j]);
mn[1][i][j]=min(mn[1][i+1][j],dp[1][i][j]);
} ll sgn=sum[1][1]-(dp[0][1][1]<<1);
// printf("%d\n",dp[0][1][1]);
printf("%s\n",(sgn>0)?"Cry":((!sgn)?"Flowers":"Break a heart"));
return 0;
}

Codeforces 536D - Tavas in Kansas(dp)的更多相关文章

  1. CodeForces - 710E Generate a String (dp)

    题意:构造一个由a组成的串,如果插入或删除一个a,花费时间x,如果使当前串长度加倍,花费时间y,问要构造一个长度为n的串,最少花费多长时间. 分析:dp[i]---构造长度为i的串需要花费的最短时间. ...

  2. Educational Codeforces Round 51 D. Bicolorings(dp)

    https://codeforces.com/contest/1051/problem/D 题意 一个2*n的矩阵,你可以用黑白格子去填充他,求联通块数目等于k的方案数,答案%998244353. 思 ...

  3. CodeForces 536D Tavas in Kansas

    洛谷题目页面传送门 & CodeForces题目页面传送门 A和B在一张无向连通图\(G=(V,E),|V|=n,|E|=m\)上玩一个游戏,节点\(i\)有一个权值\(v_i\).A.B分别 ...

  4. Codeforces 295D - Greg and Caves(dp)

    题意: 给出一个 \(n \times m\) 的矩阵,需对其进行黑白染色,使得以下条件成立: 存在区间 \([l,r]\)(\(1\leq l\leq r\leq n\)),使得第 \(l,l+1, ...

  5. Codeforces 467C George and Job(DP)

    题目 Source http://codeforces.com/contest/467/problem/C Description The new ITone 6 has been released ...

  6. Codeforces A ACM (ACronym Maker) (dp)

    http://codeforces.com/gym/100650 概要:给出一个缩写,和一些单词,从单词中按顺序选一些字母作为缩写,问方案数. 限制:某些单词要忽略,每个单词至少要选一个字母. dp[ ...

  7. codeforces 813 D. Two Melodies(dp)

    题目链接:http://codeforces.com/contest/813/problem/D 题意:求两个不相交的子集长度之和最大是多少,能放入同一子集的条件是首先顺序不能变,然后每一个相邻的要么 ...

  8. codeforces 762 D. Maximum path(dp)

    题目链接:http://codeforces.com/problemset/problem/762/D 题意:给出一个3*n的矩阵然后问从左上角到右下角最大权值是多少,而且每一个点可以走上下左右,但是 ...

  9. CodeForces - 446A DZY Loves Sequences(dp)

    题意:给定一个序列a,求最长的连续子序列b的长度,在至多修改b内一个数字(可修改为任何数字)的条件下,使得b严格递增. 分析: 1.因为至多修改一个数字,假设修改a[i], 2.若能使a[i] < ...

随机推荐

  1. html视口单位:vw,vh,rem

    前言 不像响应式布局,通过media query,设置几个变化点来适配,流体排版通过调整大小,适配所有设备宽度.这个方法可以使我们开发的网页,在几乎所有屏幕尺寸上都可以使用.但出于一些原因,它的使用率 ...

  2. Win10 配置JDK1.8 (JDK 8)环境变量

    JDK的安装: 1. JDK安装过程中,一般X掉公共JRE,因为JDK包含了JRE:     环境变量的配置: 1. 打开环境变量,编辑系统变量,新建: 变量名:JAVA_HOME 变量值:D:\so ...

  3. leetcode347 —— n中topK && PriorityQueue(Heap) && Map遍历

    题目要求:求前K个最频繁出现的数字. 1.很容易想到,使用HashMap<Integer,Integer>来存储<number,frequency>键值对 1 int n = ...

  4. airtest keyevent 按键速查表

  5. Beta实际开发与初始计划的比较

    零.说明 本篇博客为Beta阶段开始十天后,实际开发工作与初始计划的比较 截止至本篇博客发布为止,团队所有成员已完成计网考试,将在本周日进行充分的接口测试 一.比较 1.与初始计划对比 初始计划 实际 ...

  6. UltraSoft - Alpha - Scrum Meeting 7

    Date: Apr 22th, 2020. Scrum 情况汇报 进度情况 组员 负责 昨日进度 后两日任务 CookieLau PM 完成课程中心的json格式传递 完成邮箱验证机制 刘zh 前端 ...

  7. Beta阶段第二次会议

    时间:2020.5.18 工作进展 姓名 工作 难度 完成度 ltx 1.在开小程序开发文档,学习相关知识 轻 85% xyq 1.完成活动场地申请可视化代码(耗时半天) 中 100% lm 1.设计 ...

  8. spring session实现session统一管理(jdbc实现)

    最近在看一些关于spring session 的知识,特做一个笔记记录一下. 在项目中经常会遇到这么一种情况,同一个web项目有时需要部署多份,然后使用nginx实现负载均衡,那么遇到的问题就是,部署 ...

  9. freemarker中使用String字符串作为模板

    在日常开发中,我们有时候需要发送短信.邮件等通知,但是这些通知的内容通常都是动态的,而且可能会发生变动,为了程序的灵活性,我们通常会将通知的内容配置在页面上,然后后台通过渲染这些模板,来获取具体的内容 ...

  10. cURL 命令获取本机外网 IP

    1.1 查询本机外网 IP # curl dhcp.cn 134.175.159.160 1.2 输出格式为 JSON # curl dhcp.cn/?json { "IP": & ...