T1. 只不过是长的领带

大水题,把 \(a_i,b_i\) 从小到大排序。

发现最优方案只可能是大的 \(a_i\) 跟大的 \(b_i\) 匹配,小的 \(a_i\) 与小的 \(b_i\) 匹配。

故前缀后缀各算一遍最大值就行了。

#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define fz(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define ffe(it,v) for(__typeof(v.begin()) it=v.begin();it!=v.end();it++)
#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
typedef pair<int,int> pii;
typedef long long ll;
const int MAXN=2e5+5;
int n,b[MAXN];pii a[MAXN];
int pre[MAXN],suf[MAXN],ans[MAXN];
int main(){
scanf("%d",&n);
for(int i=1;i<=n+1;i++) scanf("%d",&a[i].fi),a[i].se=i;
for(int i=1;i<=n;i++) scanf("%d",&b[i]);
sort(a+1,a+n+2);sort(b+1,b+n+1);
for(int i=1;i<=n;i++) pre[i]=max(pre[i-1],max(a[i].fi-b[i],0));
for(int i=n;i;i--) suf[i]=max(suf[i+1],max(a[i+1].fi-b[i],0));
for(int i=1;i<=n+1;i++) ans[a[i].se]=max(pre[i-1],suf[i]);
for(int i=1;i<=n+1;i++) printf("%d ",ans[i]);
return 0;
}

T2. JJOOII

发现 \(1\) 操作其实是删除 \(s\) 的一个前缀,\(2\) 操作其实是删除 \(s\) 的一个后缀。

预处理出 \(nxt_{i,0/1/2}\) 表示从 \(i\) 开始最少需要扩展到什么位置才能存在 \(k\) 个 'J'/'O'/'I',双针扫一遍。

我们枚举这个前缀删了多少个字符,用 \(nxt\) 数组求出在这种情况下后缀最多删了多少个字符,更新答案即可。

时间复杂度 \(\mathcal O(n)\)。

#include <bits/stdc++.h>
using namespace std;
const int MAXN=2e5+5;
char s[MAXN];
int n,k,nxt[MAXN][3];
int main(){
scanf("%d%d%s",&n,&k,s+1);
int cur=1,num=0;
while(cur<=n&&num<k) num+=(s[cur++]=='J');cur--;
for(int i=1;i<=n+1;i++){
nxt[i][0]=cur;
if(s[i]=='J'){
if(cur!=n+1) cur++;
while(cur<=n&&s[cur]!='J') cur++;
}
}
cur=1,num=0;
while(cur<=n&&num<k) num+=(s[cur++]=='O');cur--;
for(int i=1;i<=n+1;i++){
nxt[i][1]=cur;
if(s[i]=='O'){
if(cur!=n+1) cur++;
while(cur<=n&&s[cur]!='O') cur++;
}
}
cur=1,num=0;
while(cur<=n&&num<k) num+=(s[cur++]=='I');cur--;
for(int i=1;i<=n+1;i++){
nxt[i][2]=cur;
if(s[i]=='I'){
if(cur!=n+1) cur++;
while(cur<=n&&s[cur]!='I') cur++;
}
}
int ans=n+1;
for(int i=1;i<=n;i++){
int r=nxt[i][0];
if(r!=n+1) r=nxt[r+1][1];
if(r!=n+1) r=nxt[r+1][2];
if(r!=n+1) ans=min(ans,r-i+1-(k*3));
} printf("%d\n",(ans==n+1)?(-1):ans);
}

T3. 集邮比赛

\(dp\),\(dp_{l,r,k,0/1}\) 表示逆时针收集了 \(l\) 个,顺时针收集了 \(r\) 个,当前在左边还是右边所需的最小时间。

转移从 \(dp_{l,r}\) 更新到 \(dp_{l+1,r}\) 和 \(dp_{l,r+1}\),看时间是否 \(\leq t_l\) 判断能否收集。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
template<typename T> void chkmin(T &a,T b){if(a>b) a=b;}
template<typename T> void chkmax(T &a,T b){if(a<b) a=b;}
const int MAXN=200+5;
int n,L,x[MAXN],t[MAXN],s[MAXN];
ll dp[MAXN][MAXN][MAXN][2];
int main(){
scanf("%d%d",&n,&L);
for(int i=1;i<=n;i++) scanf("%d",&x[i]);
for(int i=1;i<=n;i++) scanf("%d",&t[i]);
memset(dp,63,sizeof(dp));dp[0][0][0][0]=0;
for(int i=0;i<=n;i++) for(int j=0;j+i<n;j++){
for(int k=0;k<=i+j;k++){
chkmin(dp[i+1][j][k+((dp[i][j][k][0]+x[i+1]-x[i])<=t[i+1])][0],dp[i][j][k][0]+x[i+1]-x[i]);
chkmin(dp[i+1][j][k+((dp[i][j][k][1]+L-x[n-j+1]+x[i+1])<=t[i+1])][0],dp[i][j][k][1]+L-x[n-j+1]+x[i+1]);
chkmin(dp[i][j+1][k+((dp[i][j][k][1]+x[n-j+1]-x[n-j])<=t[n-j])][1],dp[i][j][k][1]+x[n-j+1]-x[n-j]);
chkmin(dp[i][j+1][k+((dp[i][j][k][0]+L-x[n-j]+x[i])<=t[n-j])][1],dp[i][j][k][0]+L-x[n-j]+x[i]);
}
}
int ans=0;
for(int i=0;i<=n;i++) for(int j=0;j+i<=n;j++) for(int k=0;k<=i+j;k++){
if(dp[i][j][k][0]<1e18) chkmax(ans,k);
if(dp[i][j][k][1]<1e18) chkmax(ans,k);
} printf("%d\n",ans);
}

T4. 奥运公交

这题想了好久。。。我觉得我要爆了。

首先枚举 \(m\),计算翻转每条边后 \(1 \to n\) 和 \(n \to 1\) 的最短路。

这里以 \(1 \to n\) 为例,\(n \to 1\) 同理。

翻转后 \(1 \to n\) 的最短路可以分为两种情况:经过这条边和不经过这条边。也就是不经过这条边的 \(1 \to n\) 的最短路,与不经过这条边的 \(1 \to v\) 的最短路 \(+c_i+\) 不经过这条边的 \(u \to n\) 的最短路的较小值。

不难发现不经过这条边的 \(u \to n\) 的最短路的较小值可以通过建反图归约到前一类。

于是本题就变为,如何求出不经过某条边的从源点出发到达某个点的最短路。

不难发现,不在最短路树上的边不会对答案造成影响,故如果这条边不在最短路上,那就返回原始的最短路。

否则,最短路树上的边顶多 \(n-1\) 个,你重新跑 \(n-1\) 次 dijkstra 也能接受。

怎样求最短路树?很简单,你记录每个点的前驱,它们形成的就是一个最短路树。

最后,堆优化的 dijkstra 是 \(m\log m\) 的,朴素 dijkstra 是 \(n^2\) 的。由于本题的图是稠密图,堆优化的 dijkstra 反而跑不过朴素的 dijkstra。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN=200+5;
const int MAXM=5e4+5;
int n,m,u[MAXM],v[MAXM],c[MAXM],d[MAXM];
struct graph{
int hd[MAXN],to[MAXM],nxt[MAXM],cst[MAXM],ec,from,pre[MAXN];
bool on[MAXM],vis[MAXN];
ll dist[MAXN],odist[MAXN];
void adde(int u,int v,int c){
to[++ec]=v;cst[ec]=c;nxt[ec]=hd[u];hd[u]=ec;
}
void dijkstra(int forbid){
memset(dist,63,sizeof(dist));
memset(pre,0,sizeof(pre));
memset(vis,0,sizeof(vis));
dist[from]=0;
for(int i=1;i<=n;i++){
ll mn=1e18;int x=n+1;
for(int j=1;j<=n;j++) if(dist[j]<mn&&!vis[j]) mn=dist[j],x=j;
if(x==n+1) break;vis[x]=1;
for(int e=hd[x];e;e=nxt[e]){
if(e==forbid) continue;
int y=to[e],z=cst[e];
if(dist[y]>dist[x]+z){
dist[y]=dist[x]+z;pre[y]=e;
}
}
}
}
void prework(){
dijkstra(0);
for(int i=1;i<=n;i++) odist[i]=dist[i];
// for(int i=1;i<=n;i++) printf("%lld ",odist[i]);printf("\n");
for(int i=1;i<=n;i++) on[pre[i]]=1;
}
ll calc(int e,int x){
if(!on[e]) return odist[x];
dijkstra(e);return dist[x];
}
} g[4];
int main(){
scanf("%d%d",&n,&m);
g[0].from=g[2].from=1;g[1].from=g[3].from=n;
for(int i=1;i<=m;i++){
scanf("%d%d%d%d",&u[i],&v[i],&c[i],&d[i]);
g[0].adde(u[i],v[i],c[i]);g[1].adde(u[i],v[i],c[i]);
g[2].adde(v[i],u[i],c[i]);g[3].adde(v[i],u[i],c[i]);
}
for(int i=0;i<4;i++) g[i].prework();
ll ans=g[0].odist[n]+g[1].odist[1];
for(int i=1;i<=m;i++){
ans=min(ans,
min(g[0].calc(i,n),g[0].calc(i,v[i])+g[3].calc(i,u[i])+c[i])+
min(g[1].calc(i,1),g[1].calc(i,v[i])+g[2].calc(i,u[i])+c[i])+d[i]);
}
if(ans<1e18) printf("%lld\n",ans);
else printf("-1\n");
return 0;
}

T5. 火灾

神仙题,待会儿写个题解

JOI 2020 Final 题解的更多相关文章

  1. JOI 2018 Final 题解

    题目列表:https://loj.ac/problems/search?keyword=JOI+2018+Final T1 寒冬暖炉 贪心 暴力考虑每相邻两个人之间的间隔,从小到大选取即可 #incl ...

  2. 【题解】LOJ2759. 「JOI 2014 Final」飞天鼠(最短路)

    [题解]LOJ2759. 「JOI 2014 Final」飞天鼠(最短路) 考虑最终答案的构成,一定是由很多飞行+一些上升+一些下降构成. 由于在任何一个点上升或者下降代价是一样的,所以: 对于上升操 ...

  3. 「JOI 2017 Final」JOIOI 王国

    「JOI 2017 Final」JOIOI 王国 题目描述 题目译自 JOI 2017 Final T3「 JOIOI 王国 / The Kingdom of JOIOI」 JOIOI 王国是一个 H ...

  4. 「JOI 2015 Final」分蛋糕 2

    「JOI 2015 Final」分蛋糕 2 题解 这道题让我想起了新年趣事之红包这道DP题,这道题和那道题推出来之后的做法是一样的. 我们可以定义dp[i][len][1] 表示从第i块逆时针数len ...

  5. [LOJ3014][JOI 2019 Final]独特的城市——树的直径+长链剖分

    题目链接: [JOI 2019 Final]独特的城市 对于每个点,它的答案最大就是与它距离最远的点的距离. 而如果与它距离为$x$的点有大于等于两个,那么与它距离小于等于$x$的点都不会被计入答案. ...

  6. LOJ#2351. 「JOI 2018 Final」毒蛇越狱

    LOJ#2351. 「JOI 2018 Final」毒蛇越狱 https://loj.ac/problem/2351 分析: 首先有\(2^{|?|}\)的暴力非常好做. 观察到\(min(|1|,| ...

  7. JOI 2019 Final合集

    JOI 2019 Final 合集 #3010. 「JOI 2019 Final」勇者比太郎 其实如果读懂题了就是水题了 题目就是让你求满足条件的\(JOI​\),使得\(O​\)在\(J​\)同行的 ...

  8. 【LOJ】#3014. 「JOI 2019 Final」独特的城市(长链剖分)

    LOJ#3014. 「JOI 2019 Final」独特的城市(长链剖分) 显然我们画一条直径,容易发现被统计的只可能是直径某个距离较远的端点到这个点的路径上的值 用一个栈统计可以被统计的点,然后我们 ...

  9. 「JOI 2014 Final」飞天鼠

    「JOI 2014 Final」飞天鼠 显然向上爬是没有必要的,除非会下降到地面以下,才提高到刚好为0. 到达一个点有两种情况:到达高度为0和不为0. 对于高度不为0的情况,显然花费的时间越少高度越高 ...

随机推荐

  1. 对cpu与load的理解及线上问题处理思路

    cpu如何计算 当我们执行top命令的时候,看到里面的值(主要是cpu和load)值是一直在变的,因此有必要简单了解一下Linux系统中cpu的计算方式. cpu分为系统cpu和进程.线程cpu,系统 ...

  2. nexus设置npm下载管理

    nexus设置npm下载管理 第一步 登录私服网页 第二步 创建存储空间(如果使用默认的存储空间,此步骤可省略) 第三步 输入空间的名称,点击create创建 第四步 创建仓库 npm的仓库有三种: ...

  3. 初学python-day4 字典(已更新完)

  4. [Java]Sevlet

    0 前言 对于Java程序员而言,Web服务器(如Tomcat)是后端开发绕不过去的坎.简单来看,浏览器发送HTTP请求给服务器,服务器处理后发送HTTP响应给浏览器. Web服务器负责对请求进行处理 ...

  5. SpringCloud微服务实战——搭建企业级开发框架(十一):集成OpenFeign用于微服务间调用

    作为Spring Cloud的子项目之一,Spring Cloud OpenFeign以将OpenFeign集成到Spring Boot应用中的方式,为微服务架构下服务之间的调用提供了解决方案.首先, ...

  6. jQuery实现打开网页自动弹出遮罩层或点击弹出遮罩层功能示例

    本文实例讲述了jQuery实现打开网页自动弹出遮罩层或点击弹出遮罩层功能.分享给大家供大家参考,具体如下: 弹出层:两种方式 一是打开网页就自动弹出层二是点击弹出 <!DOCTYPE html ...

  7. 整数中1出现的次数 牛客网 剑指Offer

    整数中1出现的次数 牛客网 剑指Offer 题目描述 求出113的整数中1出现的次数,并算出1001300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1.10.11.12.13因此 ...

  8. 第k短路(Dijkstra & A*)

    最短路,即第1短路有很多种求法,SPFA,Dijkstra等,但第k短路怎么求呢?其实也是基于Dijkstra:因为Dijkstra用的是堆优化,这样保证每次弹出来的都是最小值,只是求最短路只是弹出一 ...

  9. Codeforces Round #747 (Div. 2)题解

    谢天谢地,还好没掉分,还加了8分,(8分再小也是加啊)前期刚开始有点卡,不过在尽力的调整状态之后,还是顺利的将前面的水题过完了,剩下的E2和F题就过不去了,估计是能力问题,自己还是得认真补题啦. E2 ...

  10. Loto实践干货(8)loto示波器在LED台灯调光问题维修中的应用案例

    Loto实践干货(8)loto示波器在LED台灯调光问题维修中的应用案例 一位客户最近觉得觉得他的LED台灯好闪, 于是拆了看看,里面的控制板是这样的: 干掉双色调光功能,只调亮度的话闪烁的状况能好转 ...