POJ 1201 Intervals (차동 제약 시스템, 욕심 + 선분 트 리)
제목
최대 50000 개의 정수 구간 과 이 구간 에 적어도 포 함 된 정수 의 개 수 를 요구 합 니 다.
지금 은 원소 의 수량 이 가장 적은 정수 집합 을 찾 아 상기 조건 을 만족 시 키 고 가장 적은 원소 의 개수 가 얼마 인지 물 어 봐 야 한다.
문제 풀이 방법
방법 1 차 제약 시스템
d [i] 는 0 - > i - 1 구간 에 포 함 된 정수 의 개 수 를 나타 낸다.
그러면 그 중의 한 조건 l, r, c 는 d [r + 1] - d [l] > = c 를 나타 낸다.
그리고 추가 조건 0 < = d [i] - d [i - 1] < = 1 즉 d [i] - d [i - 1] > = 0, d [i - 1] - d [i] > = - 1 구체 적 인 건축 도 보기 코드
방법 2 욕심 + 선분 수
먼저 입력 한 조건 을 오른쪽 단점 에 따라 작은 것 부터 큰 것 까지 정렬 합 니 다.
그리고 어떤 조건 을 처리 할 때 l - > r 사이 에 이미 몇 개의 수가 구조의 집합 에 있 는 지 조회 합 니 다. 만약 에 이 수량 이 요구 하 는 수량 보다 크 거나 같 으 면 처리 하지 않 아 도 됩 니 다.
작 으 면 r - > l 순 으로 선택 하지 않 은 정 수 를 선택 하 세 요.
이렇게 하면 뒤에 선택 한 수 를 최대한 적 게 할 수 있 기 때문에 이곳 의 조회 와 업 데 이 트 는 선분 트 리 최적화 시간 에 코드 를 구체 적 으로 봐 야 합 니 다.
참조 코드 - 궁금 한 점 이 있 으 시 면 아래 에 댓 글 을 남 겨 주시 면 바로 답 해 드 리 겠 습 니 다.
방법 1 코드
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int INF = 1<<29;
const int maxn = 50000 + 10;
int d[maxn], L, R;
bool vis[maxn];
vector<int>E[maxn];
vector<int>W[maxn];
void spfa() {
memset(vis, 0, sizeof(vis));
for( int i=L; i<=R+1; i++ ) d[i] = -INF;
d[R+1] = 0;
vis[R+1] = 1;
queue<int>q;
q.push(R+1);
while(!q.empty()) {
int f = q.front(); q.pop(); vis[f] = false;
//printf("f = %d
", f);
for( int i=0; i<E[f].size(); i++ ) {
int v = E[f][i], w = W[f][i];
if(d[v] < d[f] + w) {
d[v] = d[f] + w;
//printf("v = %d d[v] = %d
", v, d[v]);
if(vis[v] == false) {
vis[v] = true;
q.push(v);
}
}
}
if(f < R && d[f] > d[f+1]) { //
d[f+1] = d[f];
if(vis[f+1] == false) {
vis[f+1] = true;
q.push(f+1);
}
}
if(f > L && d[f] - 1 > d[f-1]) {
d[f-1] = d[f] - 1;
if(vis[f-1] == false) {
vis[f-1] = true;
q.push(f-1);
}
}
}
}
int main() {
freopen("in", "r", stdin);
int n;
while(scanf("%d", &n) != EOF) {
L = INF, R = -INF;
for( int i=0; i<=maxn+2; i++ ) E[i].clear(), W[i].clear();
for( int i=0; i<n; i++ ) {
int l, r, c;
scanf("%d%d%d", &l, &r, &c);
//E[l] d[r+1] - d[l] >= c
E[l].push_back(r+1);
W[l].push_back(c);
L = min(L, l);
R = max(R, r+1);
}
int rt = R + 1;
for( int i=L; i<=R; i++ ) {
/*if(i != R) {
E[i].push_back(i+1);
W[i].push_back(0);
}
if(i != L) {
E[i].push_back(i-1);
W[i].push_back(-1);
}*/ // spfa
E[rt].push_back(i);
W[rt].push_back(0);
}
spfa();
printf("%d
", d[R]);
}
return 0;
}
방법 2 코드
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
#define ls (rt<<1)
#define rs ((rt<<1)|1)
#define mid ((l+r)>>1)
const int INF = 1<<29;
const int maxn = 50000 + 10;
int N[maxn*4];
bool all[maxn*4];
struct Node {
int l, r, c;
bool operator < (const Node & rhs) const {
if(r == rhs.r) return c > rhs.c;
else return r < rhs.r;
}
}a[maxn];
void pushdown(int rt, int l, int r) {
if(l == r) return ;
if(all[rt]) {
N[ls] = mid-l+1;
N[rs] = r - mid;
all[ls] = all[rs] = true;
all[rt] = false;
}
}
int query(int rt, int l, int r, int L, int R) {
pushdown(rt, l, r);
if(l == L && r == R) return N[rt];
if(R <= mid) return query(ls, l, mid, L, R);
else if(L > mid) return query(rs, mid + 1, r, L, R);
else return query(ls, l, mid, L, mid) + query(rs, mid + 1, r, mid + 1, R);
N[rt] = N[ls] + N[rs];
}
void update(int rt, int l, int r, int x, int c) {
pushdown(rt, l, r);
//printf("%d %d %d x = %d c = %d
", rt, l, r,x, c);
if(r-l+1-N[rt] == c) {
N[rt] = r-l+1;
all[rt] = true;
return ;
}
if(x <= mid) update(ls, l, mid, x, c);
else {
int tn = query(1, 0, maxn-10, mid+1, min(r,x));
tn = min(r,x)-mid-tn;
//printf("tn = %d
", tn);
if(tn < c) {
update(ls, l, mid, x, c - tn);
update(rs, mid + 1, r, x, tn);
}
else update(rs, mid + 1, r, x, c);
}
N[rt] = N[ls] + N[rs];
}
int main() {
freopen("in", "r", stdin);
int n;
while(scanf("%d", &n) != EOF) {
memset(N, 0, sizeof(N));
memset(all, 0, sizeof(all));
for( int i=0; i<n; i++ ) {
int l, r, c;
scanf("%d%d%d", &a[i].l, &a[i].r, &a[i].c);
}
sort(a, a + n);
for( int i=0; i<n; i++ ) {
int num = query(1, 0, maxn-10, a[i].l, a[i].r);
if(num >= a[i].c) continue;
a[i].c -= num;
update(1, 0, maxn-10, a[i].r, a[i].c);
}
printf("%d
", N[1]);
}
return 0;
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
정수 반전Udemy 에서 공부 한 것을 중얼거린다 Chapter3【Integer Reversal】 (예) 문자열로 숫자를 반전 (toString, split, reverse, join) 인수의 수치 (n)가 0보다 위 또는 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.