[cf115E]Linear Kingdom Races

参考了这里:http://blog.sina.com.cn/s/blog_6a6aa7830100x890.html

我们从第一条赛道往后选择,设选择到第i条赛道时最优值是f[i],这里注意f[i]表示的方案中第i条是不一定被选中的。

这里的状态转移分两种,第i条选或不选

1:不选,f[i]=f[i-1]

2:选,设连续往前一直选到第j+1条(0<=j<i),则f[i]=f[j]-cost(j+1,i)+pay(j+1,i)

(cost(j+1,i)表示从j+1到i的赛道全部修复的所需付费,即cost[j+1]+cost[j+2]+...+cost[i],pay(j+1,i)表示所有被完全包含在区间[j+1,i]内的比赛赚的钱总和)

这样我们就得到状态转移方程:

f[i]=max{f[i-1],f[j]-cost(j+1,i)+pay(j+1,i)} (0<=j<i)

初始条件f[0]=0

如果朴素转移的话时间是在O(n^2*m),我们用线段树来维护一下就没了。

(没学过线段树优化dp的可以看下面这一段来入门)

假设一个序列v[j]=f[j]-cost(j+1,i)+pay(j+1,i),只要用线段树维护它的区间[0,i-1]最大值就可以了。观察这个表达式,我们可以发现,当i增加1时,所有它之前的v值都要多减去一个cost[i],同时,对于每一个右端点恰好为i,即r=i的比赛(l,r,p),每一个下标小于l的v值都要加上一个p,换句话说,这是一个区间修改,区间查询的问题。完成状态转移后,将f[i]加入线段树的第i位即可。初始时,v序列中只有一个v[0]=0。不过这个v序列我们显然是不需要去再开一个数组来模拟它了,只是为了说得方便引入的。

cf上似乎没开边界检查?算术上溢的时候自然溢出了。

code:

  1 program cf115E;
  2 type competition=record lb,rb,p:longint; end;
  3 var tree:array[0..600000] of record flag,max:int64; end;
  4     com:array[0..200010] of competition;
  5     cost:array[0..200010] of longint;
  6     f:array[0..200010] of int64;
  7     i,j,n,m:longint;
  8     ans:int64;
  9 procedure sort(l,r:longint);
 10 var i,j,x:longint;
 11     t:competition;
 12 begin
 13   i:=l; j:=r; x:=com[(l+r)shr 1].rb;
 14   repeat
 15     while com[i].rb<x do inc(i);
 16     while com[j].rb>x do dec(j);
 17     if i<=j then
 18       begin
 19         t:=com[i];
 20         com[i]:=com[j];
 21         com[j]:=t;
 22         inc(i);
 23         dec(j);
 24       end;
 25   until i>j;
 26   if i<r then sort(i,r);
 27   if j>l then sort(l,j);
 28 end;
 29 function maxf(a,b:int64):int64;
 30 begin
 31   if a>b then exit(a) else exit(b);
 32 end;
 33 procedure pushdown(x:longint);
 34 begin
 35   tree[x+x].max:=tree[x+x].max+tree[x].flag;
 36   tree[x+x+1].max:=tree[x+x+1].max+tree[x].flag;
 37   tree[x+x].flag:=tree[x+x].flag+tree[x].flag;
 38   tree[x+x+1].flag:=tree[x+x+1].flag+tree[x].flag;
 39   tree[x].flag:=0;
 40 end;
 41 procedure edit_len(x,nowl,nowr,l,r,p:longint);
 42 var mid:longint;
 43 begin
 44   if (nowr<l)or(nowl>r) then exit;
 45   if (l<=nowl)and(nowr<=r) then
 46     begin
 47       with  tree[x] do
 48         begin
 49           flag:=flag+p;
 50           max:=max+p;
 51         end;
 52       exit;
 53     end;
 54   pushdown(x);
 55   mid:=(nowl+nowr)shr 1;
 56   edit_len(x+x,nowl,mid,l,r,p);
 57   edit_len(x+x+1,mid+1,nowr,l,r,p);
 58   tree[x].max:=maxf(tree[x+x].max,tree[x+x+1].max);
 59 end;
 60 procedure edit_point(x,nowl,nowr,posi:longint;p:int64);
 61 var mid:longint;
 62 begin
 63   if nowl=nowr then
 64     begin
 65       tree[x].flag:=p;
 66       tree[x].max:=p;
 67       exit;
 68     end;
 69   pushdown(x);
 70   mid:=(nowl+nowr) shr 1;
 71   if posi<=mid then edit_point(x+x,nowl,mid,posi,p)
 72     else edit_point(x+x+1,mid+1,nowr,posi,p);
 73   tree[x].max:=maxf(tree[x+x].max,tree[x+x+1].max);
 74 end;
 75 function find(x,nowl,nowr,l,r:longint):int64;
 76 var mid:longint;
 77 begin
 78   if (nowr<l)or(nowl>r) then exit(-maxlongint);
 79   if (nowl>=l)and(nowr<=r) then exit(tree[x].max);
 80   pushdown(x);
 81   mid:=(nowl+nowr) shr 1;
 82   find:=maxf(find(x+x,nowl,mid,l,r),find(x+x+1,mid+1,nowr,l,r));
 83 end;
 84 begin
 85   readln(n,m);
 86   for i:=1 to n do readln(cost[i]);
 87   for i:=1 to m do with com[i] do readln(lb,rb,p);
 88   sort(1,m);
 89   f[0]:=0;
 90   ans:=0;
 91   j:=1;
 92   for i:=1 to n do
 93     begin
 94       while com[j].rb=i do
 95         begin
 96           edit_len(1,0,n,0,com[j].lb-1,com[j].p);
 97           inc(j);
 98         end;
 99       edit_len(1,0,n,0,i-1,-cost[i]);
100       f[i]:=find(1,0,n,0,i-1);
101       if f[i-1]>f[i] then f[i]:=f[i-1];
102       edit_point(1,0,n,i,f[i]);
103       if f[i]>ans then ans:=f[i];
104     end;
105   writeln(f[n]);
106 end.

 

转载于:https://www.cnblogs.com/lkmcfj/p/5965574.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个基本的马拉松数据库设计: 1. Participants表 - 存储参加马拉松比赛的参与者信息 | 字段名 | 数据类型 | 描述 | | ------------ | -------- | ------------------------------------------ | | participantId | int | 参与者ID(主键) | | name | varchar | 参与者姓名 | | gender | varchar | 参与者性别 | | age | int | 参与者年龄 | | email | varchar | 参与者电子邮件地址 | | phone | varchar | 参与者电话号码 | | address | varchar | 参与者地址 | | emergency | varchar | 紧急联系人姓名和电话号码 | | health | varchar | 参与者健康状况 | | tshirtSize | varchar | 参与者所需的T恤尺码 | | raceId | int | 参与者参加的赛事ID(外键,来自Races表) | | registration | datetime | 参与者注册时间 | | payment | float | 参与者支付的费用 | | isVerified | boolean | 参与者是否已经通过了健康检查和审核(审核) | 2. Races表 - 存储马拉松比赛的信息 | 字段名 | 数据类型 | 描述 | | ---------- | -------- | --------------------------------------------------- | | raceId | int | 赛事ID(主键) | | name | varchar | 赛事名称 | | location | varchar | 赛事地点 | | date | date | 赛事日期 | | startTime | time | 赛事开始时间 | | distance | float | 赛事距离(以公里为单位) | | category | varchar | 赛事类别(如普通马拉松、半程马拉松、全程马拉松等) | | maxEntries | int | 赛事最大参与人数 | | organizer | varchar | 赛事组织者名称 | 3. Results表 - 存储参与者在比赛中的成绩 | 字段名 | 数据类型 | 描述 | | ------------ | -------- | ---------------------------------------- | | resultId | int | 结果ID(主键) | | participantId| int | 参与者ID(外键,来自Participants表) | | raceId | int | 赛事ID(外键,来自Races表) | | timeTaken | time | 参与者完成赛事所需的时间(时分秒) | | rank | int | 参与者在赛事中获得的排名 | | medal | varchar | 参与者在赛事中获得的奖牌(如金牌、银牌) | 4. Sponsors表 - 存储赞助商的信息 | 字段名 | 数据类型 | 描述 | | -------- | -------- | ---------------------------------------- | | sponsorId| int | 赞助商ID(主键) | | name | varchar | 赞助商名称 | | category | varchar | 赞助商类别(如服装、饮食、药品等) | | logo | blob | 赞助商的logo图像(二进制数据) | 5. Sponsorships表 - 存储赞助商和赛事之间的关系 | 字段名 | 数据类型 | 描述 | | ---------- | -------- | ---------------------------------------- | | sponsorshipId| int | 赞助关系ID(主键) | | raceId | int | 赛事ID(外键,来自Races表) | | sponsorId | int | 赞助商ID(外键,来自Sponsors表) | | amount | float | 赞助商支付的金额 |
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值