hdu 4719 Oh My Holy FFF(세그먼트 수 + dp)
제목 링크: hdu 4719 Oh My Holy FFF
제목의 대의: 대열에 n명이 있는데 모든 사람의 키를 주고 그들은 순서대로 배열한다. 지금 이 n명을 몇 조로 나누어야 한다. 각 조의 인원은 l보다 크면 안 된다. 그리고 i조의 마지막 사람의 키는 반드시 i-1조의 마지막 사람의 키보다 크다.마지막 값이 가장 크도록 요구합니다. 값 계산 방법은 제목에서 k가 그룹 번호입니다.
문제풀이 사고방식: dp[i]는 제i개인을 끝으로 하는 최대 권한을 나타낸다. 그러면 dp[i]는 앞의 l-1에서 옮겨온 것이 틀림없다. 즉, dp[i]=dp[j]+h[i]2-h[j]는 h[i]>h[j]를 요구한다.그러나 이러한 복잡도는 o(n2)이고 n은 최대 105이다. 시간적으로 받아들일 수 없기 때문에 라인 트리로 조회 조작을 대체한다. 그러나 이동하는 조건은 h[i]>h[j]라고 한다. 그래서 우리는 먼저 모든 사람을 키에 따라 순서를 정해야 한다. 그러면 하나하나 계산하면 키의 제한을 고려할 필요가 없다. 왜냐하면 이미 업데이트된 값이 있으면 키는 현재 고려해야 할 사람보다 작을 것이다.그리고 찾을 값 b[i]=dp[i]--h[j].세그먼트 트리가 정식으로 접촉한 적이 없기 때문에 매우 비벼서 썼고 갱신도 지연되지 않았다.
코드
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
typedef long long ll;
const int N = 1e5+5;
struct state {
int pos;
ll high;
}p[N];
struct node {
int left;
int right;
ll val;
}t[N*4];
int n, k;
ll dp[N];
inline ll max(ll a, ll b) {
return a > b ? a : b;
}
ll BuildTree (int c, int l, int r) {
t[c].left = l;
t[c].right = r;
if (l == r) {
t[c].val = -1;
} else {
int mid = (l + r)/2;
t[c].val = max(BuildTree(c*2, l, mid), BuildTree(c*2+1, mid+1, r));
}
return t[c].val;
}
ll Query (int c, int l, int r) {
if (l == t[c].left && r == t[c].right)
return t[c].val;
int mid = (t[c].left + t[c].right) / 2;
if (l <= mid && r > mid)
return max(Query(c*2, l, mid), Query(c*2+1, mid+1, r));
else if (l <= mid && r <= mid)
return Query(c*2, l, r);
else
return Query(c*2+1, l, r);
}
ll upDate (int c, int l, int r, ll val) {
if (l == t[c].left && r == t[c].right) {
t[c].val = val;
return val;
}
int mid = (t[c].left + t[c].right) / 2;
if (l <= mid && r > mid)
return t[c].val = max(upDate(c*2, l, mid, val), upDate(c*2+1, mid+1, r, val));
else if (l <= mid && r <= mid)
return t[c].val = max(upDate(c*2, l, r, val), t[c*2+1].val);
else
return t[c].val = max(t[c*2].val, upDate(c*2+1, l, r, val));
}
inline bool cmp (const state& a, const state& b) {
if (a.high != b.high)
return a.high < b.high;
return a.pos > b.pos;
}
void init () {
scanf("%d%d", &n, &k);
for (int i = 1; i <= n; i++) {
cin >> p[i].high;
p[i].pos = i;
}
sort(p+1, p+n+1, cmp);
BuildTree(1, 0, n);
}
ll solve () {
upDate(1, 0, 0, 0);
for (int i = 1; i <= n; i++) {
dp[p[i].pos] = -1;
ll val = Query(1, max(0, p[i].pos-k), p[i].pos-1);
//cout << val << " " << p[i].pos << endl;
if (val == -1)
continue;
dp[p[i].pos] = val + p[i].high * p[i].high;
if (p[i].pos == n)
break;
upDate(1, p[i].pos, p[i].pos, dp[p[i].pos] - p[i].high);
}
return dp[n];
}
int main () {
int cas;
scanf("%d", &cas);
for (int i = 1; i <= cas; i++) {
init ();
cout << "Case #" << i << ": ";
ll ans = solve();
if (ans <= 0)
cout << "No solution" << endl;
else
cout << ans << endl;
}
return 0;
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSON
JSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다.
그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다.
저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
typedef long long ll;
const int N = 1e5+5;
struct state {
int pos;
ll high;
}p[N];
struct node {
int left;
int right;
ll val;
}t[N*4];
int n, k;
ll dp[N];
inline ll max(ll a, ll b) {
return a > b ? a : b;
}
ll BuildTree (int c, int l, int r) {
t[c].left = l;
t[c].right = r;
if (l == r) {
t[c].val = -1;
} else {
int mid = (l + r)/2;
t[c].val = max(BuildTree(c*2, l, mid), BuildTree(c*2+1, mid+1, r));
}
return t[c].val;
}
ll Query (int c, int l, int r) {
if (l == t[c].left && r == t[c].right)
return t[c].val;
int mid = (t[c].left + t[c].right) / 2;
if (l <= mid && r > mid)
return max(Query(c*2, l, mid), Query(c*2+1, mid+1, r));
else if (l <= mid && r <= mid)
return Query(c*2, l, r);
else
return Query(c*2+1, l, r);
}
ll upDate (int c, int l, int r, ll val) {
if (l == t[c].left && r == t[c].right) {
t[c].val = val;
return val;
}
int mid = (t[c].left + t[c].right) / 2;
if (l <= mid && r > mid)
return t[c].val = max(upDate(c*2, l, mid, val), upDate(c*2+1, mid+1, r, val));
else if (l <= mid && r <= mid)
return t[c].val = max(upDate(c*2, l, r, val), t[c*2+1].val);
else
return t[c].val = max(t[c*2].val, upDate(c*2+1, l, r, val));
}
inline bool cmp (const state& a, const state& b) {
if (a.high != b.high)
return a.high < b.high;
return a.pos > b.pos;
}
void init () {
scanf("%d%d", &n, &k);
for (int i = 1; i <= n; i++) {
cin >> p[i].high;
p[i].pos = i;
}
sort(p+1, p+n+1, cmp);
BuildTree(1, 0, n);
}
ll solve () {
upDate(1, 0, 0, 0);
for (int i = 1; i <= n; i++) {
dp[p[i].pos] = -1;
ll val = Query(1, max(0, p[i].pos-k), p[i].pos-1);
//cout << val << " " << p[i].pos << endl;
if (val == -1)
continue;
dp[p[i].pos] = val + p[i].high * p[i].high;
if (p[i].pos == n)
break;
upDate(1, p[i].pos, p[i].pos, dp[p[i].pos] - p[i].high);
}
return dp[n];
}
int main () {
int cas;
scanf("%d", &cas);
for (int i = 1; i <= cas; i++) {
init ();
cout << "Case #" << i << ": ";
ll ans = solve();
if (ans <= 0)
cout << "No solution" << endl;
else
cout << ans << endl;
}
return 0;
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.