2024牛客多校2I Red Playing Cards
本文同步于我的博客。
Problem
There are \(2\cdot n\) cards arranged in a row, with each card numbered from \(1\) to \(n\) having exactly 2 copies.
Each time, Red can choose a subarray of consecutive cards (at least \(2\) cards) to remove from the deck. The chosen subarray must satisfy that the first and last cards have the same number. The score for this operation is: the number of cards multiplied by the number on the first card. Now Red wants to know what is the maximum value of the final score?
给你一个长度为 \(2n\) 的数组,\(1\) 到 $ n$ 每个数字恰好出现两次。你可以进行这样的操作:选择两个相同的数字 \(x\) (必须都还存在于数组中),将这两个数以及其间的所有数字(共计 \(cnt\) 个)全部拿走,并获得 \(x\cdot cnt\) 得分。求最终最多能够获得多少分?
\(1\le n\le 3\times 10^3\)
Solution
我们发现基本有这三种情况:
- 相离。比如
1 1 3 3
,1
和3
互不影响。 - 包含。比如
1 3 3 1
,可以先拿3-3
再拿1-1
,也可以直接一次拿1-1
,此时3
没有任何贡献。 - 相交。比如
1 3 1 3
,如果拿了1-1
就不能再拿3-3
了,拿了3-3
也不能再拿1-1
。
设 \(f(i)\) 为 \([l_i,r_i]\) 这段区间的最大得分。\(l_i,r_i\) 分别指第一个 \(i\) 和第二个 \(i\) 的位置。
先假设 \([l_i,r_i]\) 中每个数字的贡献都是 \(i\),而如果遇到了另一个区间 \([l_j,r_j]\) 满足 \((l_i<l_j<r_j<r_i)\),那么考虑使用 \(f(j)\) 来代替这一个子区间的贡献。
这里一定有 \(len_j<len_i\),所以我们按照区间长度 \(len_i\) 排序来计算 \(f(i)\)
那么如何计算 \(f(i)\) 呢?
设 \(g(k)\) 表示,在计算 \(f(i)\) 时,区间 \([l_i,k]\) 的最大贡献。
- 对于一般情况而言,\(g(k)=g(k-1)+i\)。
- 而如果当前 \(k\) 是某个数字 \(j\) 的第二次出现的地方,且这个数字第一次出现的地方 \(l_j\in[l_i,k]\),那么需要考虑有可能先抹去 \(j\) ,也就是取 \([l_j,r_j]\) 得分为 \(f(j)\),会使得答案更优,。
g(k)=\left\{
\begin{array}{l}
\max \left(g(k-1)+i, g\left(l_j-1\right)+f(j)\right), \text { if } k=r_j \text { and } l_j>l_i \\
g(k-1)+i, \text { otherwise }
\end{array}\right.
\end{gather}
\]
而我们需要的 \(f(i)=g(r_i)\)。
为了得到整个数组的得分,这里有个trick。我们在数组前后添加两个0
,求 \(f(0)\) 即可。
时间复杂度 \(O(n^2)\)。
Code
/**************************************************************
* Problem:
* Author: Vanilla_chan
* Date:
* E-Mail: heshaohong2015@outlook.com
**************************************************************/
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<queue>
#include<vector>
#include<limits.h>
#define IL inline
#define re register
#define LL long long
#define ULL unsigned long long
#ifdef TH
#define debug printf("Now is %d\n",__LINE__);
#else
#define debug
#endif
#ifdef ONLINE_JUDGE
char buf[1<<23],* p1=buf,* p2=buf,obuf[1<<23],* O=obuf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
#endif
using namespace std;
#define N 6010
int n;
int a[N],l[N],r[N],len[N];
bool cmp(int x,int y)
{
return len[x]<len[y];
}
vector<int>p;
int f[N],g[N];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cout.precision(10);
int t=1;
// cin>>t;
while(t--)
{
cin>>n;
for(int i=1;i<=n*2;i++)
{
cin>>a[i];
if(l[a[i]])
{
r[a[i]]=i;
len[a[i]]=i-l[a[i]]+1;
}
else l[a[i]]=i;
}
l[0]=0,r[0]=2*n+1,len[0]=2*n+2;
for(int i=0;i<=n;i++)
{
p.push_back(i);
}
sort(p.begin(),p.end(),cmp);
// for(int x=0;x<=n;x++) cout<<p[x]<<" "; cout<<endl;
for(auto x:p)
{
for(int k=l[x];k<=r[x];k++)
{
g[k]=g[k-1]+x;
int y=a[k];
if(k==r[y]&&l[y]>l[x])
{
g[k]=max(g[k],g[l[y]-1]+f[y]);
}
}
f[x]=g[r[x]];
for(int k=l[x];k<=r[x];k++) g[k]=0;
// cout<<"f["<<x<<"]="<<f[x]<<endl;
}
cout<<f[0]<<endl;
}
return 0;
}
2024牛客多校2I Red Playing Cards的更多相关文章
- 2019牛客多校第一场 I Points Division(动态规划+线段树)
2019牛客多校第一场 I Points Division(动态规划+线段树) 传送门:https://ac.nowcoder.com/acm/contest/881/I 题意: 给你n个点,每个点有 ...
- 牛客多校第一场 B Inergratiion
牛客多校第一场 B Inergratiion 传送门:https://ac.nowcoder.com/acm/contest/881/B 题意: 给你一个 [求值为多少 题解: 根据线代的知识 我们可 ...
- 2019牛客多校第二场 A Eddy Walker(概率推公式)
2019牛客多校第二场 A Eddy Walker(概率推公式) 传送门:https://ac.nowcoder.com/acm/contest/882/A 题意: 给你一个长度为n的环,标号从0~n ...
- 牛客多校第三场 F Planting Trees
牛客多校第三场 F Planting Trees 题意: 求矩阵内最大值减最小值大于k的最大子矩阵的面积 题解: 矩阵压缩的技巧 因为对于我们有用的信息只有这个矩阵内的最大值和最小值 所以我们可以将一 ...
- 牛客多校第三场 G Removing Stones(分治+线段树)
牛客多校第三场 G Removing Stones(分治+线段树) 题意: 给你n个数,问你有多少个长度不小于2的连续子序列,使得其中最大元素不大于所有元素和的一半 题解: 分治+线段树 线段树维护最 ...
- 牛客多校第四场sequence C (线段树+单调栈)
牛客多校第四场sequence C (线段树+单调栈) 传送门:https://ac.nowcoder.com/acm/contest/884/C 题意: 求一个$\max {1 \leq l \le ...
- 牛客多校第3场 J 思维+树状数组+二分
牛客多校第3场 J 思维+树状数组+二分 传送门:https://ac.nowcoder.com/acm/contest/883/J 题意: 给你q个询问,和一个队列容量f 询问有两种操作: 0.访问 ...
- 2019牛客多校第八场 F题 Flowers 计算几何+线段树
2019牛客多校第八场 F题 Flowers 先枚举出三角形内部的点D. 下面所说的旋转没有指明逆时针还是顺时针则是指逆时针旋转. 固定内部点的答案的获取 anti(A)anti(A)anti(A)或 ...
- 2019年牛客多校第一场B题Integration 数学
2019年牛客多校第一场B题 Integration 题意 给出一个公式,求值 思路 明显的化简公式题,公式是分母连乘形式,这个时候要想到拆分,那如何拆分母呢,自然是裂项,此时有很多项裂项,我们不妨从 ...
- 2020牛客多校第八场K题
__int128(例题:2020牛客多校第八场K题) 题意: 有n道菜,第i道菜的利润为\(a_i\),且有\(b_i\)盘.你要按照下列要求给顾客上菜. 1.每位顾客至少有一道菜 2.给顾客上菜时, ...
随机推荐
- 【Abaqus热分析】热膨胀系数设置
来源:帮助文档
- 音视频SDK对比|K歌App中的实时合唱功能如何进行技术选型
摘要 在线K歌软件的开发有许多技术难点,需考虑到音频录制和处理.实时音频传输和同步.音频压缩和解压缩.设备兼容性问题等技术难点外,此外,开发者还应关注音乐版权问题,确保开发的应用合规合法. 前言 前面 ...
- https证书中的subject alternative name字段作用及如何生成含该字段的证书
背景 最近,某个运维同事找到我,说测试环境的某个域名(他也在负责维护),假设域名为test.baidu.com,以前呢,证书都是用的生产的证书,最近不让用了.问为啥呢,说不安全,现在在整改了,因为证书 ...
- 解决PyCharm提示Error: Please select a valid Python interpreter
前言 Pycharm运行Python3.7.8的程序时发现源程序运行报错(非语法错误) Error:please select a valid Python interpreter 解决 第一步:打开 ...
- 堆排序(topk 问题)(NB)
博客地址:https://www.cnblogs.com/zylyehuo/ # _*_coding:utf-8_*_ # 比较排序 import random def sift(li, low, h ...
- Linux脚本-使用jar自动替换配置文件
背景 最近公司需要在生产服务器上测试字库,需要非常频繁修改配置文件中的字体相关属性,然后实时调试,所以需要频繁的修改配置文件并手动发布出去.之前需要修改配置文件时,我们需要: 把jar包通过FTP传回 ...
- golang的条件编译
写c/c++或者rust的开发者应该对条件编译不陌生,条件编译顾名思义就是在编译时让代码中的一部分生效或者失效,从而控制编译时的代码执行路径,进而影响编译出来的程序的行为. 这有啥用呢?通常在编写跨平 ...
- sql server2008出现set 选项的设置不正确:"ARITHABORT”
( SELECT STUFF(( SELECT '','' + CODE FROM INVNEWSAL11 WHERE (MASTERI=BILRCV.SRCERI) OR (LINKERI IN ( ...
- zk源码—6.Leader选举的实现原理
大纲 1.zk是如何实现数据一致性的 (1)数据一致性分析 (2)实现数据一致性的广播模式 (3)实现数据一致性的恢复模式 2.zk是如何进行Leader选举的 (1)服务器启动时的Leader选举 ...
- easy-query隐式Group革命性OLAP优化JAVA下最强查询ORM没有之一子查询合并
easy-query JAVA下最强查询ORM没有之一的任意子查询合并革命性OLAP优化 前言 对于大部分OLTP而言的查询市面上常见的orm已经能很好的处理,只要建立好对象关系那么就可以非常简单的实 ...