【38.24%】【POJ 1201】Intervals

来源:互联网 发布:前端ajax模拟数据 编辑:程序博客网 时间:2024/06/05 02:32

Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 25902 Accepted: 9905
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
Source

Southwestern Europe 2002

【题目链接】:http://poj.org/problem?id=1201

【题解】

题意:
给你m个条件ai bi ci;
表示ai..bi这些整数在序列中至少出现了ci次;
然后问你这个序列最少能由多少个数字组成;
设d[i]表示1..i这些数字里面有多少个数字;
则所给的m个条件可以写出
d[bi]-d[ai]>=ci;
然后就转化为差分约束的题了;
考虑转化为最长路

if (d[u]-d[v]<c)    d[u] = d[v]+c;


可以看到我们令d[u]=d[v]+c后实际上是让d[u]-d[v]=c;
而原本d[u]-d[v]是小于c的,而如果d[u]再变大一点也可以满足d[u]-d[v]>c但是显然直接让d[u]-d[v]=c会使得d[u]更小;
这样进行松弛操作后;整个d就是最小的了;
所以对输入的ai bi ci;
即d[bi]-d[ai]>=ci;
则在ai与bi之间建一条由ai指向bi的单向边,边权为ci;
又有0<=d[i]-d[i-1]<=1;->因为一个数字没必要出现两次;只可能有两种情况,出现一次或者不出现;

d[i]-d[i-1]>=0
d[i-1]-d[i]>=-1
再根据这两个在i-1和i之间建边权为0的边,在i和i-1之间建边权为-1的边;
然后一开始dis数组赋值为无穷小;然后从起点跑spfa即可;
但是这样还不够;有些细节要做到位
比如
2
1 2 1
2 3 1
这个输入
如果我们单纯地在ai与bi之间建一条由ai指向bi的单向边,边权为ci;
则会得到ans=2的错解;
原因在于程序没办法判断1-2和2-3是否重合了;
做法是把[ai,bi]换成[ai,bi+1);
因为是整数,所以这样的做法是正确的;
也即对于输入的ai bi ci;
直接令bi++;
然后再建边;
找到最左的端点作为s,最右的端点作为t;则从s开始跑spafa;最后输出d[t];

【完整代码】

#include <cstdio>#include <cstdlib>#include <cmath>#include <set>#include <map>#include <iostream>#include <algorithm>#include <cstring>#include <queue>#include <vector>#include <stack>#include <string>using namespace std;#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1#define LL long long#define rep1(i,a,b) for (int i = a;i <= b;i++)#define rep2(i,a,b) for (int i = a;i >= b;i--)#define mp make_pair#define pb push_back#define fi first#define se secondtypedef pair<int,int> pii;typedef pair<LL,LL> pll;void rel(LL &r){    r = 0;    char t = getchar();    while (!isdigit(t) && t!='-') t = getchar();    LL sign = 1;    if (t == '-')sign = -1;    while (!isdigit(t)) t = getchar();    while (isdigit(t)) r = r * 10 + t - '0', t = getchar();    r = r*sign;}void rei(int &r){    r = 0;    char t = getchar();    while (!isdigit(t)&&t!='-') t = getchar();    int sign = 1;    if (t == '-')sign = -1;    while (!isdigit(t)) t = getchar();    while (isdigit(t)) r = r * 10 + t - '0', t = getchar();    r = r*sign;}const int MAXM = (50000+100)*4;const int INF =-0x3f3f3f3f;const int dx[9] = {0,1,-1,0,0,-1,-1,1,1};const int dy[9] = {0,0,0,-1,1,-1,1,-1,1};const double pi = acos(-1.0);int w[MAXM],en[MAXM],fir[MAXM],nex[MAXM];int n,totm=0;void add(int x,int y,int z){    totm++;    nex[totm] = fir[x];    fir[x] = totm;    en[totm] = y;    w[totm] = z;}int main(){    //freopen("F:\\rush.txt","r",stdin);    int s = 21e8,t=0;    rei(n);    rep1(i,1,n)    {        int x,y,z;        rei(x);rei(y);rei(z);        s = min(s,x);t=max(t,y+1);        //dis[y]-dis[x]>=z        add(x,y+1,z);    }    rep1(i,s,t)    {        add(i,i+1,0);        add(i+1,i,-1);    }    int dis[MAXM];    memset(dis,INF,sizeof(dis));    dis[s] = 0;    queue <int>dl;    bool in[MAXM];    dl.push(s);in[s] = true;    while (!dl.empty())    {        int x = dl.front();        in[x] = false;        dl.pop();        for (int temp = fir[x];temp;temp=nex[temp])        {            int y = en[temp];            if (dis[y]<dis[x]+w[temp])            {                dis[y] = dis[x] + w[temp];                if (!in[y])                {                    in[y] = true;                    dl.push(y);                }            }        }    }    cout << dis[t]<<endl;    return 0;}
0 0