[JXOI2018]守卫
题意
link
个数 , 每个点可以放守卫,能覆盖他向左能看到的点,能看到定义为两点连线没有经过其它点即以下的位置。
求所有区间最小守卫数的异或和。
区间 dp
状态
表示区间最小的守卫数。
初始状态
注意到区间最右端一定要放一个守卫。
即 。
转移
考虑枚举目前区间 r 能看见的最左边的点 , 那么 就是看不到的,因此再要 或 处放守卫,也就是子区间 的子问题,
对于 也是一个子问题。
那
分析
区间dp 状态 , 转移可以做到
那么时间复杂度就是 。
代码
这个 sum 就是 只不过是顺路更新。
#include<bits/stdc++.h>
using namespace std;
//using ll = long long;
const int MAXN = 5010;
const int INF = 0x7fffffff;
const int mod = 1000000007;
const double eps = 1e-9;
template <typename T>
void Read(T &x) {
x = 0; T f = 1; char a = getchar();
for(; a < '0' || '9' < a; a = getchar()) if (a == '-') f = -f;
for(; '0' <= a && a <= '9'; a = getchar()) x = (x * 10) + (a ^ 48);
x *= f;
}
inline void add(int &a, const int &b) {
a = a + b;
if (a >= mod) a -= mod;
if (a < 0) a += mod;
}
inline int mul(const int &a, const int &b) {
return 1ll * a * b % mod;
}
int qpow(int a, int b) {
int sum(1);
while(b) {
if (b & 1) sum = mul(sum, a);
a = mul(a, a);
b >>= 1;
}
return sum;
}
int n;
int h[MAXN], f[MAXN][MAXN];
double slope(int a, int b, int c, int d) {
return 1.0 * (a - c) / (b - d);
}
int main() {
cin >> n;
for (int i = 1; i <= n; i ++) {
cin >> h[i];
}
int ans = 0;
for (int r = 1; r <= n; r ++) {
f[r][r] = 1;
ans ^= 1;
int sum = 1, p = 0;
for (int l = r - 1; l >= 1; l --) {
if (!p || slope(h[r], r, h[p], p) > slope(h[r], r, h[l], l)) {
if (p) sum += min(f[l + 1][p], f[l + 1][p - 1]);
p = l;
}
f[l][r] = sum + min(f[l][p], f[l][p - 1]);
ans ^= f[l][r];
}
}
cout << ans << endl;
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】