本文同步于我的博客

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 313互不影响。
  • 包含。比如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)\),会使得答案更优,。
\[\begin{gather}
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的更多相关文章

  1. 2019牛客多校第一场 I Points Division(动态规划+线段树)

    2019牛客多校第一场 I Points Division(动态规划+线段树) 传送门:https://ac.nowcoder.com/acm/contest/881/I 题意: 给你n个点,每个点有 ...

  2. 牛客多校第一场 B Inergratiion

    牛客多校第一场 B Inergratiion 传送门:https://ac.nowcoder.com/acm/contest/881/B 题意: 给你一个 [求值为多少 题解: 根据线代的知识 我们可 ...

  3. 2019牛客多校第二场 A Eddy Walker(概率推公式)

    2019牛客多校第二场 A Eddy Walker(概率推公式) 传送门:https://ac.nowcoder.com/acm/contest/882/A 题意: 给你一个长度为n的环,标号从0~n ...

  4. 牛客多校第三场 F Planting Trees

    牛客多校第三场 F Planting Trees 题意: 求矩阵内最大值减最小值大于k的最大子矩阵的面积 题解: 矩阵压缩的技巧 因为对于我们有用的信息只有这个矩阵内的最大值和最小值 所以我们可以将一 ...

  5. 牛客多校第三场 G Removing Stones(分治+线段树)

    牛客多校第三场 G Removing Stones(分治+线段树) 题意: 给你n个数,问你有多少个长度不小于2的连续子序列,使得其中最大元素不大于所有元素和的一半 题解: 分治+线段树 线段树维护最 ...

  6. 牛客多校第四场sequence C (线段树+单调栈)

    牛客多校第四场sequence C (线段树+单调栈) 传送门:https://ac.nowcoder.com/acm/contest/884/C 题意: 求一个$\max {1 \leq l \le ...

  7. 牛客多校第3场 J 思维+树状数组+二分

    牛客多校第3场 J 思维+树状数组+二分 传送门:https://ac.nowcoder.com/acm/contest/883/J 题意: 给你q个询问,和一个队列容量f 询问有两种操作: 0.访问 ...

  8. 2019牛客多校第八场 F题 Flowers 计算几何+线段树

    2019牛客多校第八场 F题 Flowers 先枚举出三角形内部的点D. 下面所说的旋转没有指明逆时针还是顺时针则是指逆时针旋转. 固定内部点的答案的获取 anti(A)anti(A)anti(A)或 ...

  9. 2019年牛客多校第一场B题Integration 数学

    2019年牛客多校第一场B题 Integration 题意 给出一个公式,求值 思路 明显的化简公式题,公式是分母连乘形式,这个时候要想到拆分,那如何拆分母呢,自然是裂项,此时有很多项裂项,我们不妨从 ...

  10. 2020牛客多校第八场K题

    __int128(例题:2020牛客多校第八场K题) 题意: 有n道菜,第i道菜的利润为\(a_i\),且有\(b_i\)盘.你要按照下列要求给顾客上菜. 1.每位顾客至少有一道菜 2.给顾客上菜时, ...

随机推荐

  1. 【Abaqus】材料行为的非均匀空间分布

    设想一种情况:在有限元分析中,一个区域或者整个网格中,每个单元的材料行为都是单独的.这时在ABAQUS中应该如何设置? 两种办法: 给每个单元创建一个集合,然后一一赋予SECTION. 使用*Dist ...

  2. gitee如何删除仓库

    进入仓库的管理页面点击删除

  3. golang interface 转 string、int、float64

    interface{} interface{} 接口.interface{} 类型很多人都会混淆.interface{} 类型是没有方法的接口.由于没有 implements 关键字,所以说所有的类型 ...

  4. Windows 提权-服务_弱服务权限

    本文通过 Google 翻译 Weak Service Permissions – Windows Privilege Escalation 这篇文章所产生,本人仅是对机器翻译中部分表达别扭的字词进行 ...

  5. .NET原生操作向量数据库实战系列(一):.向量数据库的应用以及与AI结合的畅想

    在当今数据驱动的时代,向量数据库(Vector Database)作为一种新兴的数据库技术,正逐渐成为软件开发领域的重要组成部分.特别是在 .NET 生态系统中,向量数据库的应用为开发者提供了构建智能 ...

  6. BUUCTF---达芬奇的密码

    题目 达芬奇隐藏在蒙娜丽莎中的数字列:1 233 3 2584 1346269 144 5 196418 21 1597 610 377 10946 89 514229 987 8 55 6765 2 ...

  7. How to grow old

    An individual human existence should be like a river-small at first,narrowly contained within its ba ...

  8. 初识for循环

    1.格式 想象成跑3圈,初始化语句是i=1,即第一圈,判断条件就是i<=3,跑完三圈就停,条件控制语句就是i++,跑完一圈就要在心里加1圈. . 2.for循环的执行流程 1.执行初始化语句,在 ...

  9. 【SpringCloud】微服务架构编码构建

    微服务架构编码构建 约定>配置>编码 Mysql的主从 slave会从master读取binlog来进行数据同步 三步骤+原理图 MySQL复制过程分成三步: master将改变记录到二进 ...

  10. Global.asax 转

    备忘: 项目中的Global.asax文件里通常包含这5个方法: Application_Start – web 应用程序最初启动时执行 Application_End – 应用程序关闭时运行 App ...