标签:names 前缀和 lse 图片 温习 com push close 题解
秒了,然后因为没开ll调了一个上午顺便叉掉了两份标
把每个点看做(s到其的最短路,t到其的最短路),等同于在坐标系上有一些点,每次把xy轴向上移,贡献为新扫到的点
离散化,设f[i][j]表示先手扫到i,后手扫到j之后的最大差值,设g表示最小差值
然后用前缀和转移一下即可,注意每次一定要走到至少一个城市
温习了一下dij
#include <bits/stdc++.h>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
#define ll long long
//#define file
using namespace std;
struct type{ll x,id;} b[2001];
bool operator < (type a,type b) {return a.x>b.x;}
int a[200001][3],ls[2001],w[2001],sum2[2002][2002],lsf[2002][2002],lsg[2002][2002],h,t,n,m,i,j,k,l,st,ed,x,y,z,len;
ll X[2001],Y[2001],f[2002][2002],g[2002][2002],F[2002][2002],G[2002][2002],sum[2002][2002];
priority_queue<type> heap;
void New(int x,int y,int z) {++len;a[len][0]=y;a[len][1]=ls[x];ls[x]=len;a[len][2]=z;}
bool cmp(type a,type b) {return a.x<b.x;}
void bfs(int st,ll *f)
{
int i,j,k,l;
ll s;
memset(f,127,2001*8);f[st]=0;
heap.push({0,st});
while (!heap.empty())
{
k=heap.top().id;s=heap.top().x;heap.pop();
if (f[k]<s) continue;
for (i=ls[k]; i; i=a[i][1])
if (f[a[i][0]]>f[k]+a[i][2])
f[a[i][0]]=f[k]+a[i][2],heap.push({f[a[i][0]],a[i][0]});
}
}
void turn(ll *a)
{
int i,j,k,l;
fo(i,1,n) b[i]={a[i],i};
sort(b+1,b+n+1,cmp);
j=0;
fo(i,1,n) j+=i==1 || b[i].x!=b[i-1].x,a[b[i].id]=j;
}
int main()
{
#ifdef file
freopen("CF536D.in","r",stdin);
#endif
scanf("%d%d",&n,&m);
scanf("%d%d",&st,&ed);
fo(i,1,n) scanf("%d",&w[i]);
fo(i,1,m) scanf("%d%d%d",&x,&y,&z),New(x,y,z),New(y,x,z);
bfs(st,X),bfs(ed,Y);
turn(X),turn(Y);
fo(i,1,n) sum[X[i]][Y[i]]+=w[i],++sum2[X[i]][Y[i]];
fd(i,n,0)
{
fd(j,n,0)
sum[i][j]+=sum[i+1][j]+sum[i][j+1]-sum[i+1][j+1],sum2[i][j]+=sum2[i+1][j]+sum2[i][j+1]-sum2[i+1][j+1];
}
fd(i,n,0)
{
fd(j,n,0)
{
lsf[i][j]=lsf[i+1][j];
lsg[i][j]=lsg[i][j+1];
if (sum2[i+1][j+1])
{
f[i][j]=sum[i+1][j+1]+F[lsf[i][j]][j];
g[i][j]=-sum[i+1][j+1]+G[i][lsg[i][j]];
}
F[i][j]=max(F[i+1][j],g[i][j]-sum[i+1][j+1]);
G[i][j]=min(G[i][j+1],f[i][j]+sum[i+1][j+1]);
if (sum2[i][j+1]>sum2[i+1][j+1]) lsf[i][j]=i;
if (sum2[i+1][j]>sum2[i+1][j+1]) lsg[i][j]=j;
}
}
if (!f[0][0])
printf("Flowers\n");
else
printf(f[0][0]>0?"Break a heart\n":"Cry\n");
fclose(stdin);
fclose(stdout);
return 0;
}
标签:names 前缀和 lse 图片 温习 com push close 题解
原文地址:https://www.cnblogs.com/gmh77/p/12813589.html