zoukankan      html  css  js  c++  java
  • 做作业-贪心-并查集

    Description

      暑假到了,小明的老师们布置了一系列共N个作业给大家做。由于作业的相关性,考虑到同学们假期要去社会实践,同学们只需做完连续的一段作业即可。每个作业有俩个参数,需要的时间长度和难度系数。老师怕同学们太偷懒,要求连续的一段作业总时间必须不小于指定的M。小明是特别害怕做难题,因此想请学编程的你帮他选出一段作业,既能满足老师要求,其最大难度作业的难度又最小。

    Input

      第一行:两个空格分开的数N(1≤N≤100,000) 和M(1≤M≤10^18);
      以下N行:两个空格分开的数Ti,Si,表示第i个作业的长度和难度(1≤Ti≤109,1≤Si≤109)

    Output

      输出仅一个整数表示选出的这段作业的最大难度。

    Sample Input

    5 10
    4 10
    6 15
    3 5
    4 9
    3 6
    Sample Output
    9
    Hint

    【数据范围】

      40%的数据满足,N<=1000;
      100%的数据满足,N<=100,000


    思路

    • 贪心,并查集合并。将作业按难度升序排列,优先选难度低的作业。选的过程中合并原始顺序相邻的作业(相邻的区间成一个连通块/集合),当某次合并后,区间总和大于M,此时的难度即为答案。

    代码

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #define maxn 100005
    using namespace std;
    int n,f[maxn],flag[maxn];
    long long m,s[maxn];
    struct fdfdfd{int x,y,id;}a[maxn];
    bool cmp(fdfdfd a,fdfdfd b){return a.y<b.y;}
    int getfa(int x){return f[x]==x?x:f[x]=getfa(f[x]);}
    void merge(int x,int y)
    {
        x=getfa(x);y=getfa(y);
        s[x]+=s[y];
        f[y]=x;
    }
    int main()
    {
        scanf("%d%lld",&n,&m);
    	for(int i=1;i<=n;++i) scanf("%d%d",&a[i].x,&a[i].y),a[i].id=f[i]=i,s[i]=a[i].x;
        sort(a+1,a+n+1,cmp);
        for(int i=1;i<=n;++i)
        {
            int id=a[i].id; flag[id]=1;
            if(flag[id-1]) merge(id,id-1);
            if(flag[id+1]) merge(id,id+1);
            if(s[getfa(id)]>=m) {printf("%d
    ",a[i].y); break;}
        }
    }
    
  • 相关阅读:
    动态内存Treap
    最大流Dinic
    图的遍历
    Aho_Corasick自动机(AC自动机)
    邻接表
    COJ 3007 Mr.Yang的小助手
    COJ 0601&0602 动态规划(二)及加强
    Codeforces 603A Alternative Thinking
    HDU 2222 Keywords Search
    codeforce--600D
  • 原文地址:https://www.cnblogs.com/wuwendongxi/p/13365502.html
Copyright © 2011-2022 走看看