Intervals


Description

You are given n closed, integer intervals [ai, bi] and n integers c1, ..., cn. 
Write a program that: 
reads the number of intervals, their end points and integers c1, ..., cn from the standard input, 
computes the minimal size of a set Z of integers which has at least ci common elements with interval [ai, bi], for each i=1,2,...,n, 
writes the answer to the standard output. 

Input

The first line of the input contains an integer n (1 <= n <= 50000) -- the number of intervals. The following n lines describe the intervals. The (i+1)-th line of the input contains three integers ai, bi and ci separated by single spaces and such that 0 <= ai <= bi <= 50000 and 1 <= ci <= bi - ai+1.

Output

The output contains exactly one integer equal to the minimal size of set Z sharing at least ci elements with interval [ai, bi], for each i=1,2,...,n.

Sample Input

5
3 7 3
8 10 3
6 8 1
1 3 1
10 11 1

Sample Output

6

这个题开始用的简单队列,结果超时了,然后就用了数组来存。而且开始拉掉了一个条件s[i+1]-s[i]<=1

这个题有:0<=s[i+1]-s[i]<=1(s[i]-s[i+1]>=-1)  s[b]-s[a]>=w

因为是求最小值所以用>=

#include <iostream>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
#define oo 1<<28
#include<queue>
struct node
{
    int u;
    int v;
    int w;
    int next;
} edge[1100000];
int n,m,s,t;
using namespace std;
int cnt;
int dis[51000];
int head[51000];
int vist[51000];
int pre[51000];
int num[51000];
void add(int u,int v,int w)
{
    edge[cnt].u=u;
    edge[cnt].v=v;
    edge[cnt].w=w;
    edge[cnt].next=head[u];
    head[u]=cnt++;
}
void init()
{
    for(int i=0; i<=n+1; i++)
    {
        dis[i]=-oo;
    }
    memset(pre,-1,sizeof(pre));
    memset(vist,0,sizeof(vist));
    memset(num,0,sizeof(num));
}
void Spfa()
{
    int i,cou=0;
    init();
    int q[35000];//用单纯的队列会超时
    dis[s]=0;
    vist[s]=1;
    q[cou++]=s;
    while(cou)
    {
        cou--;
        int t=q[cou];
        i=head[t];
        vist[t]=0;
        while(i!=-1)
        {
            int v=edge[i].v;
            int u=edge[i].u;
            int w=edge[i].w;
            if(dis[v]<w+dis[t])
            {
                dis[v]=w+dis[t];
                if(!vist[v])
                {
                    vist[v]=1;
                    q[cou++]=v;
                }
            }
            i=edge[i].next;
        }
    }
    printf("%d\n",dis[t]-dis[s]);
}
int main()
{
    int i,j;
    char str[1000];
    while(~scanf("%d",&n))
    {
        int u,v,w;
        int maxx=0,minn=oo;
        cnt=0;
        memset(head,-1,sizeof(head));
        for(i=1; i<=n; i++)
        {
            scanf("%d%d%d",&u,&v,&w);
            add(u,v+1,w);//s[v+1]-[u]>=w求最小值用>=
            minn=min(u,minn);
            maxx=max(v+1,maxx);
        }
        s=minn,t=maxx;
        for(i=minn;i<maxx;i++)
        {
            add(i,i+1,0);//s[i+1]-s[i]>=0
            add(i+1,i,-1);//开始拉掉了这个条件然后看的题解发现s[i+1]-s[i]<=1--->s[i]-s[i+1]>=-1
        }
        Spfa();
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值