遭遇战

  背景 Background
    你知道吗,SQ Class的人都很喜欢打CS。
描述 Description
  今天,他们在打一张叫DUSTII的地图,万恶的恐怖分子要炸掉藏在A区的SQC论坛服务器!我们SQC的人誓死不屈,即将于恐怖分子展开激战,准备让一个人守着A区,这样恐怖分子就不能炸掉服务器了。(一个人就能守住??这人是机械战警还是霹雳游侠?)
但是问题随之出现了,由于DustII中风景秀丽,而且不收门票,所以n名反恐精英们很喜欢在这里散步,喝茶。他们不愿意去单独守在荒无人烟的A区,在指挥官的一再命令下,他们终于妥协了,但是他们每个人都要求能继续旅游,于是给出了自己的空闲时间,而且你强大的情报系统告诉了你恐怖份子计划的进攻时间(从s时刻到e时刻)。
当然,精明的SQC成员不会为你免费服务,他们还要收取一定的佣金(注意,只要你聘用这个队员,不论他的执勤时间多少,都要付所有被要求的佣金)。身为指挥官的你,看看口袋里不多的资金(上头真抠!),需要安排一个计划,雇佣一些队员,让他们在保证在进攻时间里每时每刻都有人员执勤,花费的最少资金。
输入格式 Input Format
  第一行是三个整数n(1≤n≤10000),s和e(0≤s≤e≤90000)。
接下来n行,描述每个反恐队员的信息:空闲的时间si, ei(0≤si≤ei≤90000)和佣金ci(1≤ci≤300000)。
输出格式 Output Format
  一个整数,最少需支付的佣金,如果无解,输出“-1”。

 

题意就是用若干个带有价值的区间去覆盖一个指定区间问最小代价。

先按左端点排序,然后DP。

设左端点为s[i],右端点为t[i],价值为c[i]。

f[t[i]]:=min(f[j]+c[i])=min(f[j])+c[i]  s[i]-1<=j<=t[i]

min(f[j])的过程是区间取最大值的过程,用线段树可以很快完成。

再把f[t[i]]插入线段树维护即可。

 

AC CODE

 

program tyvj_1504;
const maxn=99999999999999999;
var a:array[1..820000] of int64;
    s,t,c:array[1..20000] of longint;
    f:array[0..100010] of int64;
    len,n,w,p,q,ss,tt:longint;
    cost:int64;
//============================================================================
procedure qsort(l,r:longint);
var k,i,j,tt:longint;
begin
  k:=s[(l+r) shr 1]; i:=l; j:=r;
  repeat
    while s[i]<k do inc(i);
    while s[j]>k do dec(j);
    if i<=j then
    begin
      tt:=t[i]; t[i]:=t[j]; t[j]:=tt;
      tt:=s[i]; s[i]:=s[j]; s[j]:=tt;
      tt:=c[i]; c[i]:=c[j]; c[j]:=tt;
      inc(i); dec(j);
    end;
  until i>j;
  if j>l then qsort(l,j);
  if i<r then qsort(i,r);
end;
//============================================================================
procedure init;
var be,en,i:longint;
begin
  readln(n,ss,tt);
  inc(ss); inc(tt);
  for i:=1 to n do
  begin
    readln(s[i],t[i],c[i]);
    inc(s[i]); inc(t[i]);
  end; qsort(1,n); len:=90001;
  for i:=0 to len do f[i]:=maxn;
  for i:=1 to len*8 do a[i]:=maxn;
end;
//============================================================================
function min(x,y:int64):int64;
begin
  if x<y then min:=x else min:=y;
end;
//============================================================================
procedure ask(be,en,now:longint);
var mid:longint;
begin
  if (be>=p) and (en<=q) then
  begin
    cost:=min(cost,a[now]);
    exit;
  end;
  mid:=(be+en) shr 1;
  if p<=mid then ask(be,mid,now shl 1);
  if q>mid then ask(mid+1,en,now shl 1+1);
end;
//============================================================================
procedure ins(be,en,now:longint);
var mid:longint;
begin
  if be=en then
  begin a[now]:=f[w]; exit; end;
  mid:=(be+en) shr 1;
  if w<=mid then ins(be,mid,now shl 1) else
  ins(mid+1,en,now shl 1+1);
  a[now]:=min(a[now],f[w]);
end;
//============================================================================
procedure DP;
var i:longint;
begin
  w:=ss-1; f[w]:=0;
  ins(0,len,1);
  for i:=1 to n do
  begin
    p:=s[i]-1; q:=t[i]; cost:=maxn;
    ask(0,len,1);
    f[t[i]]:=min(f[t[i]],cost+c[i]);
    w:=t[i]; ins(0,len,1);
  end;
  cost:=maxn; p:=tt; q:=len;
  ask(0,len,1);
  if cost<maxn then writeln(cost) else
  writeln('-1');
end;
//============================================================================
begin
  init;
  DP;
end.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值