疯狂的bLue(拓扑序+离散化)

疯狂的bLue
Time Limit: 1000MS Memory Limit: 65536KB
Submit Statistic
Problem Description

众所周知神秘的 ACM 实验室有一个史诗级的出题狂魔,名曰 bLue。最近 bLue 又露出了邪恶的笑,原来是 bLue 接了为校赛出题的单子。
距离校赛开始还有 N 小时,由于各种奇怪的原因出题组可以出题的时间并不固定,大致可以分为M个时间段。每个时间段可以出的题目数也可能不同。同时由于出题是个煞费心血的事情,所以每个出题时间段结束后,善良的 bLue 会让大家休息 R (1 ≤ R ≤ N ) 小时,以便为接下来的出题事业继续奋斗。
为了能为校赛准备尽可能多的题目以备不时之需,bLue 需要好好地规划好这 N 小时如何安排,当然作为唯一的长者,bLue 一下子就为大家规划好了如何安排出题的时间段。
现在 bLue 想考考你在他完美的安排下出题组最多可以出多少个题目?
Input

测试数据有多组,输入直到文件结束。
对于每组数据:
第一行输入三个数 N (1 ≤ N ≤ 1,000,000), M (1 ≤ M ≤ 1,000), R (1 ≤ R ≤ N)
接下来有 M 行输入,每一行输入三个数 Si (0 ≤ Si < N), Ei (Si < Ei ≤ N) ,Vi (1 ≤ Vi ≤ 1,000,000) (0 < i <= M),分别表示为第 i 个时间段的开始时间,第 i 段的结束时间,第 i 个时间段可以出的题目数
Output

对于每组数据,输出出题组最多可以出的题的数目。
Example Input

15 5 3
1 4 5
6 9 4
3 5 2
7 10 8
11 15 2
Example Output

13
Hint

假设出题组在第 5 小时出完了一个时间段的题,他们需要休息 3 小时 (R = 3),那么他们在第 8 小时又可以继续开始出题了。
代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=2e4+10;
const int mod=1e7+9;
int read(){
    int x=0;char ch = getchar();
    while('0'>ch||ch>'9')ch=getchar();
    while('0'<=ch&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    return x;
}
struct node
{
    int l,r,w;
}a[1100];
vector<int>p;
inline int getid(int x)
{
    return lower_bound(p.begin(),p.end(),x)-p.begin()+1;
}
int n,m,k,sz;
int head[N*40];
int der[N];
int dis[N];
struct nod
{
    int to,next,w;
}edge[N*40];
int cnt;
inline void add(int f,int to,int w)
{
    der[to]++;
    edge[cnt].to=to;
    edge[cnt].w=w;
    edge[cnt].next=head[f];
    head[f]=cnt++;
}
void init()
{
    memset(head,-1,sizeof(head));
    cnt=0;
    memset(der,0,sizeof(der));
    p.clear();
}
void solve()
{
    queue<int>q;
    memset(dis,0,sizeof(dis));
    for(int i=1;i<=sz;i++)
    {
        if(der[i]==0)
        q.push(i);
    }
     int ans=0;
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        for(int i=head[u];i!=-1;i=edge[i].next)
        {
            int v=edge[i].to;
            int w=edge[i].w;
            if(dis[v]<dis[u]+w)
            {
                dis[v]=dis[u]+w;
                ans=max(ans,dis[v]);
            }
            der[v]--;
            if(der[v]==0)
            q.push(v);
        }
    }
    printf("%d\n",ans);
}
int main()
{
  while(~scanf("%d%d%d",&n,&m,&k))
  {
      init();
      for(int i=1;i<=m;i++)
      {
          a[i].l=read();
          a[i].r=read();
          a[i].w=read();
          p.push_back(a[i].l);
          p.push_back(a[i].r);
          p.push_back(a[i].r+k);
      }
      sort(p.begin(),p.end()),p.erase(unique(p.begin(),p.end()),p.end());
      sz=p.size();
      for(int i=1;i<=sz;i++)
      add(i,i+1,0);
      for(int i=1;i<=m;i++)
      {
       add(getid(a[i].l),getid(a[i].r+k),a[i].w);   
      }
      solve();
  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值