poj-3171 Cleaning Shifts

呂振麒 bio photo By 呂振麒 Comment

傳送門:

Cleaning Shifts

題意:

給 N 個區間,每個區間[s,t] 有一個權值 v ,求覆蓋整個區間需要的最低權值。

思路:

很快我們就可以想到dp方法,令dp[i]為從頭覆蓋到i的最低權值,則我們將所有區間依照t排序後枚舉來做狀態轉移。

對於一個區間 [s,t]:v ,可以接在 [s-1,t) 後方,於是我們掃過 dp[s-1] ~ dp[t-1],試看看 dp[] + v 是否能更新 dp[t]。

這樣做會超時,但我們如果將所有 dp 用個線段樹來維護,剛剛的操作就變成區間詢問最小,以及單點修改。

詳細往下看 code內註解吧!

code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
typedef long long ll;

struct Node{
  int x, y;
  ll val;
  Node(int a=0, int b=0, ll c=0):
    x(a), y(b), val(c){}
  bool operator < (const Node& a)const{	        // 依照t排序	
    return ((y==a.y) ? (x<a.x) : (y<a.y));
  }
};
const ll INF = 0x7f7f7f7f7f7f7f7fll;
const int VN = 87000;
typedef ll ele;

ele segt_arr[4*VN];
int segt_sz;

inline void segt_pull(int v) {
  segt_arr[v] = min(segt_arr[v<<1], segt_arr[v<<1|1]);
}
inline void segt_push(int v) {

}
void segt_update(int L, int val, int l=0, int r=segt_sz, int v=1) {
  if(l>=L && r<=L+1) segt_arr[v] = val;
  else {
    segt_push(v);
    if((l+r)>>1 >= L+1) segt_update(L, val, l, (l+r)>>1, v<<1);
    if((l+r)>>1 <= L) segt_update(L, val, (l+r)>>1, r, v<<1|1);
    segt_pull(v);
  }
}
ll segt_query(int L, int R, int l=0, int r=segt_sz, int v=1) {
  if(l>=L && r<=R) return segt_arr[v];
  if(l>=R || r<=L) return INF;
  segt_push(v);
  return min( segt_query(L, R, l, (l+r)>>1, v<<1), 
      segt_query(L, R, (l+r)>>1, r, v<<1|1));
}

int N, M, E;

Node inter[VN]; 
ll dp[VN];

void init() {
  int l, r, v, n=0;
  memset(dp, 0x7f, sizeof(dp));
  memset(segt_arr, 0x7f, sizeof(segt_arr));
  scanf("%d %d %d", &N, &M, &E);
  segt_sz = E+1;
  for(int i=0; i<N; ++i) {
    scanf("%d %d %d", &l, &r, &v);
    if(l==M) {                          // 與頭相連的區間就直接更新完扔掉
      if(dp[r] > v) {
        dp[r] = v;
        segt_update(r, v);
      }
    }
    else inter[n++] = Node(l, r, (ll)v);
  }
  N = n;
}

void sol() {
  ll q;
  sort(inter, inter+N);
  for(int i=0; i<N; ++i) {
    q = segt_query(inter[i].x-1, inter[i].y) + inter[i].val;      // 詢問最小
    if(q < dp[inter[i].y]) {
      dp[inter[i].y] = q;
      segt_update(inter[i].y, q);             // 更新
    }
  }
  if(dp[E] == INF) puts("-1");
  else printf("%lld\n", dp[E]);
}

int main() {
  init();
  sol();
}
comments powered by Disqus