Sue的小球

名次排序问题

方块消除

奥运物流

Sue的小球

题目大意

有 \(n\) 个小球在下落,初始位置 \((x_i,y_i)\),下落速度为 \(v_i\)。你初始位置在 \(x_0\),速度为 \(1\)。我们定义一个小球的贡献为接到它的时候它的纵坐标。问接到每个小球(接只接一次)的贡献之和的最大值。

\(n\le 10^3\)。

思路

算是为dp开了另外一种思路。

首先你发现,我们贪心一下,肯定每次选没选且最靠近当前位置的小球,具体证明不是很难。形式化一下,就是说按横坐标排序之后,假设已经接到 \(l\sim r\),那么下次一定接 \(l-1\) 或者 \(r+1\)。

于是,我们可以设 \(dp_{l,r,0/1}\) 表示接到 \(l\sim r\) 这段区间当前是在 \(l/r\) 时的小球的最大贡献。然后你发现这样很合理,但是你不好进行转移,因为你不能算出当前的时间。

但是转念一想,我们发现,如果我们能够在计算每个小球就把当前没有接到的小球消失的贡献都去掉的话就没有这种问题了。于是我们可以设 \(w_{l,r}=\sum_{i=1}^n v_i-\sum_{i=l}^{r}v_i\),那么我们可以得到转移式:

\[dp_{l,r,0}\to y_l+\max\{dp_{l+1,r,0}-w_{l+1,r}\times (x_{l+1}-x_l),dp_{l+1,r,1}-w_{l+1,r}\times (x_r-x_l)\}
\]

\(dp_{l,r,1}\) 同理。时间复杂度 \(\Theta(n^2)\)。

\(\texttt{Code}\)

#include <bits/stdc++.h>
using namespace std; #define Int register int
#define MAXN 1005 struct node{
int x,y,v;
bool operator < (const node &p)const{return x < p.x;}
}fuck[MAXN]; int n,x0,w[MAXN][MAXN],f1[MAXN][MAXN],f2[MAXN][MAXN]; template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');} int Abs (int x){return x > 0 ? x : -x;} signed main(){
read (n,x0);int tot = 0;
for (Int i = 1;i <= n;++ i) read (fuck[i].x);
for (Int i = 1;i <= n;++ i) read (fuck[i].y);
for (Int i = 1;i <= n;++ i) read (fuck[i].v),tot += fuck[i].v;
sort (fuck + 1,fuck + n + 1);
memset (f1,0xcf,sizeof (f1));
memset (f2,0xcf,sizeof (f2));
for (Int i = 1;i <= n;++ i)
for (Int j = i,sum = 0;j <= n;++ j) sum += fuck[j].v,w[i][j] = tot - sum;
for (Int i = 1;i <= n;++ i) f1[i][i] = f2[i][i] = fuck[i].y - Abs (x0 - fuck[i].x) * tot;
for (Int i = n;i >= 1;-- i)
for (Int j = i + 1;j <= n;++ j)
f1[i][j] = max (f1[i][j],fuck[i].y + f1[i + 1][j] - (fuck[i + 1].x - fuck[i].x) * w[i + 1][j]),
f1[i][j] = max (f1[i][j],fuck[i].y + f2[i + 1][j] - (fuck[j].x - fuck[i].x) * w[i + 1][j]),
f2[i][j] = max (f2[i][j],fuck[j].y + f1[i][j - 1] - (fuck[j].x - fuck[i].x) * w[i][j - 1]),
f2[i][j] = max (f2[i][j],fuck[j].y + f2[i][j - 1] - (fuck[j].x - fuck[j - 1].x) * w[i][j - 1]);
printf ("%.3f\n",max (f1[1][n],f2[1][n]) / 1000.0);
return 0;
}

名次排序问题

题目大意

给出一个 \(n\) 个点的序列 \(a_{1,2,...,n}\),每次可以把 \(i\) 换到 \(j\),贡献是 \(i+j\) ,问最后变成一个单调下降序列的最小贡献时的交换次数。

\(n\le 10^3\),保证 \(a_i\) 互不相等。

思路

论文

luogu上没有,如果有的话一定是个黑题吧。

首先我们可以转移题意,转换成一个权值 \(\in [1,n]\) 的序列,变为 \(1\sim n\) 的最小贡献。

然后你发现这个东西有以下 \(2\) 个性质:

  • 每个点只会交换一次

  • 交换一定权值从大到小进行

第一个显然,第二个可以靠猜(反正我猜中了)或者感性理解。

于是我们得到一个几个推论:

  1. 对于每一个数 \(x\),你在移动时有两种选择,1、 移动到数 \(x+1\) 前面,或者如果 \(x\) 的位置小于 \(x+1\) 的位置,那么可以不移动,等待后面 \(x\) 到 \(x+1\) 之间的数都移动走。

  2. 对于每一个数 \(x\),比它小的数相对位置不变。(相对位置就是指谁在前谁在后)

  3. 对于每一个数 \(x\),比 \(x+1\) 大的数都一定在 \(x+1\) 后面。

后面 2 个推论可以从第 1 个推出来,这里就不讲了。(因为跟主旨无关(是不是该夸夸我详略得当(伦敦雾

但是我们发现我们光知道相对位置没有什么用啊,我们得知道确切位置才可以啊。其实知道相对位置是做得到的。

我们发现对于一个数 \(x\) ,如果 \(x+1\sim n\) 都移动完了,那么当前位置其实就是 \(1\sim pos_x\) 中比 \(x\) 小的数 \(+1\) ,其中 \(pos_x\) 就是 \(x\) 在原序列的位置。这个可以从推论 2 看出来。

然后你发现还是不好搞,于是我们修改一下规则,把移动 \(i\to j\) 变为 \(i\) 加入 \(j\) 所在的点。然后你发现这样做的话,你就不会移动点了,而且点之间的相对位置也不会改变。(具体例子可以看论文)

接着我们设 \(c(p,x)\) 表示原序列中 \(1\sim p\) 中比 \(x\) 小的数 \(+1\)。然后我们发现如果 \(pos_i<j\) ,把 \(i\) 移动到 \(j\) 的贡献其实就是 \(c(pos_i,i)+c(j,i+1)-1\)(\(-1\) 是因为移动到 \(j-1\) 前面)。\(pos_i>j\) 同理。

于是我们考虑设 \(dp_{i,j}\) 表示已经考虑了 \(i+1\sim n\),且点 \(i\) 移动到 \(j\) 的最小贡献。对于第1中选择,转移式就是:

\[dp_{i,j}=dp_{i+1,j}+c(pos_i,i)+1+c(j,i)+1
\]

这里的式子跟上面不一样是因为这个式子归纳了 \(pos_i>j\) 的情况。

我们还需要考虑第2中情况,即它不变时的方案。注意到这篇论文的内容 我们发现我们需要考虑当前不动对后面的影响。你发现对于中间( \(x\) 和移动到的点之间)未考虑的点 \(i\) 它一定会移动到 \(x\) 的前面去,那么轮到 \(i\) 的时候 \(x\) 的前面已经排了 \(x-1,x-2,...,i+1\),所以它还需要额外算上 \(x-i\),剩下的部分会在上面考虑到。对于移动到的点之后的点肯定在轮到移动到的点的时候就考虑到了。

于是转移式就是:

\[dp_{i,pos_i}=\min\{dp_{i+1,j}+\sum_{k=i+1}^{j-1}[a_k<i](i-a_k)\}
\]

(\(a_k\) 是序列第 \(k\) 个)

于是我们就可以在 \(\Theta(n^2)\) 的时间复杂度内解决这个问题了。

不过我们要求最后的答案的话我们需要统计一下每一个点移动的点,具体可以见代码。

\(\texttt{Code}\)

#include <bits/stdc++.h>
using namespace std; #define Int register int
#define INF 0x7f7f7f7f
#define MAXN 1005 int n,tot,pos[MAXN],dp[MAXN][MAXN],pre[MAXN]; struct node{
int x,ind;
}fuck[MAXN]; bool cmp1 (node a,node b){return a.x > b.x;}
bool cmp2 (node a,node b){return a.ind < b.ind;} template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');} void dfs (int i,int j){
if (i == n) return ;
if (pos[i] != j) tot ++,dfs (i + 1,j);
else dfs (i + 1,pre[i]);
} signed main(){
read (n);
for (Int i = 1;i <= n;++ i) read (fuck[i].x),fuck[i].ind = i;
sort (fuck + 1,fuck + n + 1,cmp1);
for (Int i = 1;i <= n;++ i) pos[i] = fuck[i].ind,fuck[i].x = i;
sort (fuck + 1,fuck + n + 1,cmp2);
memset (dp,0x7f,sizeof (dp));
++ n,dp[n][n] = 0,fuck[n].x = n;
for (Int i = n - 1;i;-- i){
int v1 = 1,v2 = 1;
for (Int j = 1;j < pos[i];++ j) v1 += (fuck[j].x < i);
for (Int j = 1;j <= n;++ j) v2 += (fuck[j].x < i),dp[i][j] = min (dp[i][j],dp[i + 1][j] + v1 + v2);
for (Int j = pos[i] + 1,tmp = 0;j <= n;++ j){
if (dp[i + 1][j] + tmp < dp[i][pos[i]]) dp[i][pos[i]] = dp[i + 1][j] + tmp,pre[i] = j;
if (fuck[j].x < i) tmp += i - fuck[j].x;
}
}
int ans = 0x7f7f7f7f,pos = 0;
for (Int i = 1;i <= n;++ i) if (dp[1][i] < ans) ans = dp[1][i],pos = i;
dfs (1,pos),write (tot),putchar ('\n');
return 0;
}

参考博客

https://www.cnblogs.com/yimmortal/p/10160630.html 建议与论文一起服用

https://blog.csdn.net/icefox_zhx/article/details/80014541 可以看一下代码实现(或者看我的也可以)

方块消除

题目大意

有一个数列,每次可以消掉一掉连续的颜色相同的一块,贡献就是 \(x^2\),其中 \(x\) 是长度。问最大贡献。

思路

不知道如何去讲思考过程,所以直接讲方法?

我们可以设 \(f_{l,r,i}\) 表示消掉 \(l,r\) 并且假设在 \(r\) 的右边存在一个长度为 \(i\) 并颜色与 \(r\) 相同的块的最大贡献。于是我们可以得到转移式:

\[f_{l,r,i}=f_{l,r-1,0}+(len_r+i)^2
\]
\[f_{l,r,i}\to f_{l,j,i+len_r}+f_{j+1,r-1,0}
\]

显然,想一下就明白了。最后答案就是 \(f_{1,n,0}\)

\(\texttt{Code}\)

#include <bits/stdc++.h>
using namespace std; #define Int register int
#define MAXN 205 template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');} int sqr (int x){return x * x;}
int n,col[MAXN],pre[MAXN],len[MAXN],dp[MAXN][MAXN][MAXN]; signed main(){
read (n);
for (Int i = 1;i <= n;++ i) read (col[i]);
for (Int i = 1;i <= n;++ i) read (len[i]),pre[i] = pre[i - 1] + len[i];
for (Int leng = 1;leng <= n;++ leng){
for (Int l = 1;l + leng - 1 <= n;++ l){
int r = l + leng - 1;
for (Int i = 0;i <= pre[n] - pre[r];++ i) dp[l][r][i] = dp[l][r - 1][0] + sqr (len[r] + i);
for (Int i = l;i <= r - 1;++ i)
for (Int j = 0;j <= pre[n] - pre[r];++ j)
if (col[i] == col[r]) dp[l][r][j] = max (dp[l][r][j],dp[l][i][len[r] + j] + dp[i + 1][r - 1][0]);
}
}
write (dp[1][n][0]),putchar ('\n');
return 0;
}

奥运物流

题目大意

有一个 \(n\) 个点的图,给出参数 \(k\),每个点有一个后继,每个点有两个参数,分别为 \(R(x),C(x)\),其中 \(C(x)\) 是给定参数,\(R(x)\) 由 \(C(x)\) 计算,公式为:

\[R(x)=C(x)+k\sum_{v\in son_u}R(v)
\]

现在你有 \(m\) 次修改机会,每次可以更改一个点的后继。求 \(R(1)\) 的最大值。

思路

下面定义 \(d(i)\) 表示 \(i\to 1\) 的距离。

首先我们发现这个图一定是一个森林,就是很多棵树,然后树的根构成一个环。

我们发现对于对于一个点 \(x\),他对 \(R(1)\) 的贡献就是 \(C(x)\times k^{d(x)}/(1-k^{len})\),其中 \(len\) 是环上点的数量。具体说明可以分类讨论,分别考虑环上的点以及树上的点来说明。

然后我们如果枚举环的长度的话,那么我们就只需要让 \(\sum_{x=1}^{n}C(x)\times k^{d(x)}\) 最大。这个问题就类似于没有上司的舞会。

我们考虑设计状态 \(dp_{u,i,d}\) 表示以 \(u\) 为根的子树改变了 \(i\) 次,点 \(i\) 深度为 \(d\) 的最大贡献。于是,我们可以得到转移式:

\[dp_{u,i,d}\to dp_{u,j,d}+\max\{dp_{v,i-j,d+1}+dp_{v,i-j-1,1}\}
\]

转移显然。

最后再把环上的点都合并起来就行了。在实现的时候为了方便我们可以直接破环,把整个图变成一棵树,以 \(1\) 为根做上述 \(\text{dp}\) 即可。

时间复杂度最坏 \(\Theta(n^5)\) (假设 \(n,m\) 同阶)

\(\texttt{Code}\)

#include <bits/stdc++.h>
using namespace std; #define double long double
#define Int register int
#define MAXN 65 template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');} int n,m,s[MAXN];
vector <int> G[MAXN];
double k,c[MAXN],pw[MAXN],tmp[MAXN][MAXN],dp[MAXN][MAXN][MAXN]; void dfs (int u,int dep,int up){
for (Int i = 0;i <= up;++ i) for (Int j = 0;j <= dep;++ j) dp[u][i][j] = c[u] * pw[j];
for (Int v : G[u]){
dfs (v,dep + 1,up);
memset (tmp,0,sizeof (tmp));
for (Int i = 0;i <= up;++ i)
for (Int j = 0;i + j <= up;++ j)
for (Int d = 0;d <= dep;++ d){
tmp[i + j][d] = max (tmp[i + j][d],dp[u][i][d] + dp[v][j][d + 1]);
if (j > 0) tmp[i + j][d] = max (tmp[i + j][d],dp[u][i][d] + dp[v][j - 1][1]);
}
for (Int i = 0;i <= up;++ i) for (Int j = 0;j <= dep;++ j) dp[u][i][j] = tmp[i][j];
}
} double calc (int up){
dfs (1,0,up);
return dp[1][up][0];
} signed main(){
read (n,m);scanf ("%Lf",&k);
pw[0] = 1;for (Int i = 1;i <= n;++ i) pw[i] = pw[i - 1] * k;
for (Int i = 1;i <= n;++ i) read (s[i]);
for (Int i = 1;i <= n;++ i) scanf ("%Lf",&c[i]);
double ans = 0;
for (Int d = 2,p = s[1];p != 1;++ d,p = s[p]){
for (Int i = 1;i <= n;++ i) G[i].clear ();
int t = s[p];s[p] = 1;
for (Int i = 2;i <= n;++ i) G[s[i]].push_back (i);
ans = max (ans,calc (m - (t != 1)) / (1 - pw[d]));
s[p] = t;
}
printf ("%.2Lf\n",ans);
return 0;
}

题解 Sue的小球/名次排序问题/方块消除/奥运物流的更多相关文章

  1. BZOJ-2037 Sue的小球 DP+费用提前

    似乎很早时学长考过很类似的? 2037: [Sdoi2008]Sue的小球 Time Limit: 10 Sec Memory Limit: 64 MB Submit: 558 Solved: 300 ...

  2. 【BZOJ2037】Sue的小球(动态规划)

    [BZOJ2037]Sue的小球(动态规划) 题面 BZOJ 题解 莫名想到这道题目 很明显是一样的 设\(f[i][j][0/1]\)表示已经接到了\(i-j\)这一段的小球 当前在\(i\)或者在 ...

  3. 【BZOJ2037】[Sdoi2008]Sue的小球 区间DP+费用提前

    [BZOJ2037][Sdoi2008]Sue的小球 Description Sue和Sandy最近迷上了一个电脑游戏,这个游戏的故事发在美丽神秘并且充满刺激的大海上,Sue有一支轻便小巧的小船.然而 ...

  4. 2037: [Sdoi2008]Sue的小球

    2037: [Sdoi2008]Sue的小球 链接 题解 论文 代码 #include<cstdio> #include<algorithm> #include<cstr ...

  5. [Luogu2135] 方块消除【区间Dp】

    Online Judge:P2135 方块消除(这题不用预处理) Label:区间Dp 题目描述 Jimmy最近迷上了一款叫做方块消除的游戏.游戏规则如下:n个带颜色方格排成一列,相同颜色的方块连成一 ...

  6. 第八讲:HTML5中canvas实现小球击打小方块游戏

    源码:http://download.csdn.net/detail/liumingm900913/7469969 游戏开发流程: 1.创建画布: 将画布放在div标签里面,这样能够控制画布居中的位置 ...

  7. [BNUZOJ1261][ACM][2016北理校赛]方块消除(栈,字符串)

    玩过方块消除游戏吗?现在规定当有两个或两个以上相邻且颜色相同的方块在一起的时候,它们就会产生消除反应.当存在多个消除反应同时产生时,最下的反应先执行.现在只给你其中一列,求最后剩下的方块结果. 输入要 ...

  8. 洛谷 P2466 Sue的小球 解题报告

    P2466 [SDOI2008]Sue的小球 题目描述 Sue和Sandy最近迷上了一个电脑游戏,这个游戏的故事发在美丽神秘并且充满刺激的大海上,Sue有一支轻便小巧的小船.然而,Sue的目标并不是当 ...

  9. P2135 方块消除

    题目描述 Jimmy最近迷上了一款叫做方块消除的游戏.游戏规则如下:n个带颜色方格排成一列,相同颜色的方块连成一个区域(如果两个相邻方块颜色相同,则这两个方块属于同一区域).为简化题目,将连起来的同一 ...

随机推荐

  1. 用C++实现的增强Euler筛法程序

    运行示例 PS H:\Read\num\x64\Release> .\eulerSievePro EulerSievePro: a method to find out all primes b ...

  2. 三.Go微服务--令牌桶实现原理

    1. 前言 在上一篇文章 Go微服务: 令牌桶 当中简单的介绍了令牌桶实现的原理,然后利用 /x/time/rate 这个库 10 行代码写了一个基于 ip 的 gin 限流中间件,那这个功能是怎么实 ...

  3. Sentry Web 性能监控 - Web Vitals

    系列 1 分钟快速使用 Docker 上手最新版 Sentry-CLI - 创建版本 快速使用 Docker 上手 Sentry-CLI - 30 秒上手 Source Maps Sentry For ...

  4. WEB漏洞——XSS

    跨站脚本( Cross-site Scripting,简称为XSS或跨站脚本或跨站脚本攻击)是一种针对网站应用程序的安全漏洞攻击技术,是代码注入的一种. XSS攻击可以分为三种:反射型.存储型和DOM ...

  5. Intel® QAT加速卡之性能简介

    Intel QuickAssist Adapter 8950 设备简介 支持英特尔QuickAssist技术的英特尔QuickAssist适配器提供加密加速和压缩加速服务. 1. Key featur ...

  6. 史上最详细的信号使用说明(已被收藏和N次)

    Unix环境高级编程(第三版) 第10章 信号 文章目录 1. 引言 2. 信号的概念 2.1 信号操作之忽略信号 2.2 信号操作之捕捉信号 2.3 信号操作之执行系统默认操作 2.4 常见的信号 ...

  7. FastAPI(2)- 快速入门

    安装 FastAPI pip install fastapi # 将来需要将应用程序部署到生产环境可以安装 uvicorn 作为服务器 pip install uvicorn 最简单的代码栗子 fro ...

  8. 了解HTTP基本知识板块

    一.HTTP 协议概述 HTTP协议采用了请求/响座模型. 客户端向服务器发送-个请求,请求头包含请求的方法.URT..协议版本.以以 及包含请求修饰符.客户信息和内容的类似于MIME的消息结构. 服 ...

  9. Prism+WPF使用DependencyInjection实现AutoMapper的依赖注入功能

    前言 在使用PRISM+WPF开发项目的过程中,需要使用AutoMapper实现对象-对象的映射功能.无奈PRISM没有相关对AutoMapper相关的类库,于是转换一下思想,在nuget 中存在有关 ...

  10. Request 获取根据页面获取用户输入判断登陆成功或者失败

    import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.serv ...