您的位置:首页 > 大数据 > 人工智能

2014 Multi-University Training Contest 9 部分题目解题报告

2014-08-20 10:11 519 查看
http://acm.hdu.edu.cn/search.php?field=problem&key=2014%20Multi-University%20Training%20Contest%209&source=1&searchmode=source

SYSU出题,感觉变成了手速场。。

HDOJ 4960 Another OCD Patient

题意:一个n<=5000的序列,每个数v[i],可以合并连续的一段加和为一个数,合并一段长度为i的费用为a[i],合并过的不能再合并。问使序列成为对称的序列的最小费用。

分析:显然会是dp。然后并不是很好想= =。。只能yy一些四维五维的dp。这时先贪心地处理一下。考虑两侧,如果不相等,只能向内合并直到相等,这样就可以每次给比较小的一侧多合并一块,直到相等,那么这一大块是至少要合并的一块,递归处理可以得到一个新的已经对称的序列,这时候数的值已经不重要了,只要记录每个块是由多少个数得到的。又想到有对称性,所以其实我们只要对一侧做dp。dp[i]表示前i块和对面的后i块合并的最小费用,dp[i] = min(dp[j] + cost(j+1, i) + cost(对面的j到i)),这就是1d1d的dp,直接2500^2地做。然后我们再枚举i,把dp[i]和对应中间剩下的一段的cost加上,取个最小的。

#include<cstdio>
#include<cstring>
using namespace std;

int n, m;
long long sum[100100];
int ll[100100], dam[100100];
int main()
{
while(scanf("%d", &n) && n)
{
scanf("%d", &m);
int l, r, d;
memset(ll, 0, sizeof(ll));
for (int i = 0; i < m; i++){
scanf("%d %d %d", &l, &r, &d);
ll[l] += d; ll[r+1] += -d;
}
dam[0] = 0; sum[n+1] = 0;
for (int i = 1; i <= n; i++) dam[i] = dam[i-1] + ll[i];
for (int i = n; i >= 1; i--) sum[i] = sum[i+1] + dam[i];
int k, ans = 0, pos;
long long h;
scanf("%d", &k);
for (int i = 0; i < k; i++){
scanf("%lld %d", &h, &pos);
if (sum[pos] < h) ans++;
}
printf("%d\n", ans);
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: