1. 程式人生 > >洛谷 P1607 [USACO09FEB]廟會班車Fair Shuttle 解題報告

洛谷 P1607 [USACO09FEB]廟會班車Fair Shuttle 解題報告

upd imu \n sin friend 幫助 fin limit problem

P1607 [USACO09FEB]廟會班車Fair Shuttle

題目描述

Although Farmer John has no problems walking around the fair to collect prizes or see the shows, his cows are not in such good shape; a full day of walking around the fair leaves them exhausted. To help them enjoy the fair, FJ has arranged for a shuttle truck to take the cows from place to place in the fairgrounds.

FJ couldn‘t afford a really great shuttle, so the shuttle he rented traverses its route only once (!) and makes N (1 <= N <= 20,000) stops (conveniently numbered 1..N) along its path. A total of K (1 <= K <= 50,000) groups of cows conveniently numbered 1..K wish to use the shuttle, each of the M_i (1 <= M_i <= N) cows in group i wanting to ride from one stop S_i (1 <= S_i < E_i) to another stop E_i (S_i < E_i <= N) farther along the route.

The shuttle might not be able to pick up an entire group of cows (since it has limited capacity) but can pick up partial groups as appropriate.

Given the capacity C (1 <= C <= 100) of the shuttle truck and the descriptions of the groups of cows that want to visit various sites at the fair, determine the maximum number of cows that can ride the shuttle during the fair.

逛逛集市,兌兌獎品,看看節目對農夫約翰來說不算什麽,可是他的奶牛們非常缺乏鍛煉——如果要逛完一整天的集市,他們一定會筋疲力盡的。所以為了讓奶牛們也能愉快地逛集市,約翰準備讓奶牛們在集市上以車代步。但是,約翰木有錢,他租來的班車只能在集市上沿直線跑一次,而且只能停靠N(1 ≤N≤20000)個地點(所有地點都以1到N之間的一個數字來表示)。現在奶牛們分成K(1≤K≤50000)個小組,第i 組有Mi(1 ≤Mi≤N)頭奶牛,他們希望從Si跑到Ti(1 ≤Si<Ti≤N)。

由於班車容量有限,可能載不下所有想乘車的奶牛們,此時也允許小裏的一部分奶牛分開乘坐班車。約翰經過調查得知班車的容量是C(1≤C≤100),請你幫助約翰計劃一個盡可能滿足更多奶牛願望的方案。

輸入輸出格式

輸入格式:

第一行:包括三個整數:K,N和C,彼此用空格隔開。

第二行到K+1行:在第i+1行,將會告訴你第i組奶牛的信息:Si,Ei和Mi,彼

此用空格隔開。

輸出格式:

第一行:可以坐班車的奶牛的最大頭數。


這題的做法還是比較多噠

一看是區間選不選之類的那不就是排個序然後想辦法貪心貪心唄雲雲

按左端點排序

拿一顆平衡樹維護在車上的奶牛的右端點

當有左端點進來時,權值小於這顆左端點的點下車

然後上車上到車滿

然後比一比右端點,把右端點大的踢出去


Code:

#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <ctime>
const int N=5e4+10;
int kk,n,c;//k個區間,n個時間,c的容量
struct node
{
    int s,t,m;
    bool friend operator <(node n1,node n2)
    {
        return n1.s<n2.s;
    }
}gro[N];
int root,dat[N<<6],siz[N<<6],ch[N<<6][2],val[N<<6],tot;
#define ls ch[now][0]
#define rs ch[now][1]
void updata(int now)
{
    siz[now]=siz[ls]+siz[rs]+1;
}
void split(int now,int k,int &x,int &y)
{
    if(!now) {x=y=0;return;}
    if(dat[now]<=k)
    {
        x=now;
        split(rs,k,rs,y);
    }
    else
    {
        y=now;
        split(ls,k,x,ls);
    }
    updata(now);
}
int Merge(int x,int y)
{
    if(!x||!y) return x+y;
    if(val[x]>val[y])
    {
        ch[x][1]=Merge(ch[x][1],y);
        updata(x);
        return x;
    }
    else
    {
        ch[y][0]=Merge(x,ch[y][0]);
        updata(y);
        return y;
    }
}
int New(int k)
{
    dat[++tot]=k,val[tot]=rand(),siz[tot]=1;
    return tot;
}
void Insert(int k)
{
    int x,y;
    split(root,k,x,y);
    root=Merge(x,Merge(New(k),y));
}
void extrack(int k)
{
    int x,y,z;
    split(root,k,x,y);
    split(x,k-1,x,z);
    z=Merge(ch[z][0],ch[z][1]);
    root=Merge(x,Merge(z,y));
}
int mx()
{
    int now=root;
    while(rs) now=rs;
    return dat[now];
}
int mi()
{
    int now=root;
    while(ls) now=ls;
    return dat[now];
}
int main()
{
    srand(time(0));
    scanf("%d%d%d",&kk,&n,&c);
    for(int i=1;i<=kk;i++)
        scanf("%d%d%d",&gro[i].s,&gro[i].t,&gro[i].m);
    std::sort(gro+1,gro+1+kk);
    int ans=0;
    for(int i=1;i<=kk;i++)
    {
        int mmi,mmx;
        while(siz[root]&&(mmi=mi())<=gro[i].s) extrack(mmi),++ans;//下車
        while(gro[i].m&&siz[root]<c) Insert(gro[i].t),--gro[i].m;//上車
        while(gro[i].m&&(mmx=mx())>gro[i].t) extrack(mmx),Insert(gro[i].t),--gro[i].m;
        //踢人
    }
    printf("%d\n",ans+siz[root]);
    return 0;
}

2018.8.28

洛谷 P1607 [USACO09FEB]廟會班車Fair Shuttle 解題報告