2019UMS培训day3解题报告

T1:赌徒

链接:https://www.luogu.org/problem/T92080

$sol1:$设$f[i][j]$表示目前得到了$x$分,此时骰子面朝$i$,那么$f[i+k][k]=max(f[i][j]+1,f[i+k][k])$。

先预处理之后直接查询即可。

总复杂度$O(n)$。

$sol2:$考虑最小步数,则先去用$5,6$使之后次数更小,然后用其他面去凑,注意$7$的特判。

代码$(sol1)$:

#include <bits/stdc++.h>
const int MAXN = 1000001;
const int INF = 1 << 30;
using namespace std;
int f[MAXN][10], t, n;
void init() {
    memset(f, 127, sizeof(f)); f[0][1] = 0; for(int i = 0; i <= MAXN; i++) { for(int j = 1; j <= 6; j++) { for(int k = 1; k <= 6; k++) { if(j != k && j + k != 7) f[i + k][k] = min(f[i + k][k], f[i][j] + 1); } } } } int dp(int x) { int ans = INF; for(int i = 1; i <= 6; i++) ans = min(ans, f[x][i]); return ans; } int main() { cin >> t; init(); while(t--) { cin >> n; cout << dp(n) << endl; } return 0; } 

T2:盒子

链接:https://www.luogu.org/problem/T92083

$sol:$设$A[l][r]$表示人处于先手,在$l,r$的范围内进行选择,得到的最优答案,反之$B[l][r]$表示人处于后手......

那么一个人得到的最大的分即可以表示为$f[l][r]=max(A[l+1][r]+a[l],B[l][r-1]+a[r])$。

对于$B[l][r]$,因为是后手,所以可以直接求出。

注意要使用记忆化搜索。

最后答案即为$A(1,n)-B(1,n)$。

代码:

#include <bits/stdc++.h>
const int MAXN = 1050;
using namespace std;
int t, n, a[MAXN], sum[MAXN], f[MAXN][MAXN];
int A(int l, int r);
int B(int l, int r);
int B(int l, int r) { return sum[r] - sum[l - 1] - A(l, r); } int A(int l, int r) { if(l == r) return a[l]; if(f[l][r]) return f[l][r]; f[l][r] = max(B(l + 1, r) + a[l], B(l, r - 1) + a[r]); return f[l][r]; } void init() { memset(f, 0, sizeof(f)); } int main() { cin >> t; for(int i = 1; i <= t; i++) { cin >> n; for(int i = 1; i <= n; i++) { cin >> a[i]; sum[i] = sum[i - 1] + a[i]; } cout << A(1, n) - B(1, n) << endl; init(); } return 0; }

T3:楼房修建

链接:https://www.luogu.org/problem/P4198

$sol1:$这道题本质就是求区间内的最长斜率上升子序列,考虑用线段树维护。

线段树里维护该区间的斜率最大值,以及仅该区间的最长斜率上升子序列。

斜率的$pushup$很简单,对于后者,考虑到修改一个点,对其左侧的答案没有影响,那我们可以去递归其右子树。

对于右子树,把当前区间从中划分为两部分,若左边区间的斜率最大值都比当前传进来的斜率要小,那么只用去递归右子树。

否则答案即为递归左子树的答案加上$ans[p]-ans[ls]$。

做法很玄学。

$sol2:$分块(咕)

代码$(sol1)$:

#include <bits/stdc++.h>
#define ls p << 1
#define rs p << 1 | 1
const int MAXN = 100050;
using namespace std;
struct node {
    double Max;
}a[MAXN << 2];
int n, m, x, y, ans[MAXN << 2]; int read() { int x = 0; bool sign = false; char alpha = 0; while(!isdigit(alpha)) { sign |= alpha == '-'; alpha = getchar(); } while(isdigit(alpha)) { x = (x << 1) + (x << 3) + (alpha ^ 48); alpha = getchar(); } return sign ? -x : x; } struct Segment_Tree { void push_up(int p) { a[p].Max = max(a[ls].Max, a[rs].Max); } int query(int p, int l, int r, double k) { if(a[p].Max <= k) return 0; if(l == r) return a[p].Max > k; int mid = (l + r) >> 1; if(a[ls].Max <= k) return query(rs, mid + 1, r, k); else return query(ls, l, mid, k) + ans[p] - ans[ls]; } void update(int p, int l, int r, int x, double k) { if(l == r) { ans[p] = 1; a[p].Max = k; return ; } int mid = (l + r) >> 1; if(x <= mid) update(ls, l, mid, x, k); if(x > mid) update(rs, mid + 1, r, x, k); push_up(p); ans[p] = ans[ls] + query(rs, mid + 1, r, a[ls].Max); } }Tree; int main() { n = read(); m = read(); for(int i = 1, x, y;i <= m; i++) { x = read(); y = read(); Tree.update(1, 1, n, x, (double)y / x); cout << ans[1] << endl; } return 0; }

T4:弹飞绵羊

$sol1:$分块

(咕)

转载于:https://www.cnblogs.com/BeyondLimits/p/11311664.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值