1. 程式人生 > >Gym 101806T Touch The Sky

Gym 101806T Touch The Sky

href ould 增加 define fine wan calc typedef pen

http://codeforces.com/gym/101806/problem/T

題目

In the year 2117, Professor Jaemin Yu developed a linear-time algorithm for TSP(Traveling Salesperson Problem). Not long after that happened, all computer systems were destroyed, and nuclear weapons demolished all the lands. You, a great computer expert, also lost your job. With a great despair, you lost your meaning of life long ago. All those things that made your heart beat – where had they gone? After questioning yourself again and again, your conclusion is ...

"If I go to KAIST where I started my first ICPC, can I find a meaning of my life?"

All transportations were destroyed, but you were an avid ICPC participant, and you collected a lot of century-old balloons in Korean Regionals. If you could float a house with some of those balloons...

Currently you have N

balloons, and you are trying to float the house into the sky by attaching balloons on the rooftop. Every balloon have altitude limit Li and capacity Di, which indicates you can blow balloons in altitude at most Li, and the balloon busts after increasing the altitude by Di.

Your journey starts at altitude 0. If you have more than 1 balloons enlarged, then the house will ascend too fast. Thus, you will blow one balloon and attach it at the rooftop, increase the altitude until the balloons bust, blow the other balloon and attach it to increase the altitude... to make your house float. For convenience, you may assume that balloons can only increase the altitude.

You don‘t care about your final altitude, but a balloon can move a fixed amount of distance. Thus, you want to bust as many balloons as possible. You want to calculate a maximum number of balloons you can bust, and check if you can make a journey to KAIST. Let‘s see whether your 100-year-old ICPC experience can help on this problem!

Input

The first line contains N, the number of balloons. (1 ≤ N ≤ 250, 000)

In next N lines, the altitude limit of i-th balloon Li, and capacity of i-th balloon Di are given as two space-separated integers. (0 ≤ Li ≤ 1015, 1 ≤ Di ≤ 109)

Output

Print the maximum number of balloons you can bust.

題解

類似於UVA 1153

但是發現個問題,按照$L_i$從小到大排序後再用堆將當前任務與之前的任務交換的做法會WA

而按照$L_i+D_i$從小到大排序後再用堆將當前任務與之前的任務交換的做法會AC

按照順序考慮選氣球的問題,將考慮第$a_i$個氣球(按照某個順序選某個特定的氣球)設為第$i$個階段,解為選擇的氣球數,第1個階段很容易得到最大的解是什麽

數學歸納法,假設之前考慮的階段都已經達到最大的解了,現在考慮這一階段(這個氣球是否選)

  1. 這一階段的解肯定小於等於“上一階段的答案+1”,因為如果大於“上一階段的答案+1”,那麽
    • 如果這個答案包含這一階段的氣球,那麽可以丟掉這個氣球作為之前那個階段的解,與假設矛盾
    • 如果這個答案不包含這一階段的氣球,那麽可以直接作為之前那個階段的解,與假設矛盾
  2. 這一階段的最大的解肯定大於等於“上一階段的答案”,因為可以直接把上一階段的答案拿過來用

因此每一個階段只需要考慮答案是+1還是維持不變(註意,只考慮了數量沒有考慮選什麽,選的順序)

也就是,在之前是最優解的情況下

  1. 如果能增加氣球,那麽可以保證不會丟最優解
  2. 保持氣球不變並不能保證不會丟(現在的)最優解

因此我們必須保證不能增加氣球的時候才不增加氣球= =(這不是廢話嗎……)

每一階段都是考慮的氣球的數量,而不是哪一個氣球,因此要在丟掉某些氣球、選另外一些氣球、改變順序仍然無法增加氣球數量時才保持不變

為了簡化,我們按照順序考慮每一個氣球

考慮丟掉某些氣球,選另外一些氣球:

  • 讓另外的氣球裏包含當前考慮的氣球(增加),剩余的氣球都在前面考慮了(丟掉+選變成替換……)

考慮改變順序

  • 讓選氣球的順序就是最好的順序,不用管改變順序

因此問題就變成了確定選氣球的順序

假設是$a+b$和$c+d$

肯定能至少選一個,如果$b\leqslant c$,不交換順序能完成兩個,如果$d\leqslant a$,交換順序能完成兩個

變下形,$b+d\leqslant c+d$,$b+d\leqslant a+b$,得到$c+d$大時不交換,$a+b$大時交換

我太弱智了,寫了一大坨結果還是不會,本來是想練手寫堆的

AC代碼

#include<cstdio>
#include<cstdlib>
#include<cctype>
#include<cstring>
#include<algorithm>
#include<set>
#include<cassert>
#define REP(r,x,y) for(register int r=(x); r<(y); r++)
#define REPE(r,x,y) for(register int r=(x); r<=(y); r++)
#define PERE(r,x,y) for(register int r=(x); r>=(y); r--)
#ifdef sahdsg
#define DBG(...) printf(__VA_ARGS__),fflush(stdout)
#else
#define DBG(...) (void)0
#endif
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;

char ch; int si;
char buf[1<<21],*p1=buf,*p2=buf;
int beof = 0;
#define gc() (beof?EOF:(p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?(beof=EOF):*p1++))
#define gl(x) {char*s=x;while(isspace(*s=gc()));s++;while(!isspace(*s=gc()))s++;*s=0;}

template<class T>
inline void read(T &x) {
    x=0; si=1; for(ch=gc();!isdigit(ch) && ch!=‘-‘;ch=gc()) if(beof) return;
    if(ch==‘-‘){si=-1,ch=gc();} for(;isdigit(ch);ch=gc())x=x*10+ch-‘0‘;
    x*=si;
}
//template<class T, class...A> inline void read(T &x, A&...a){read(x); read(a...);}

#define MAXN 250007
struct node {
    LL l, d;
} hp[MAXN];
inline bool cmp(const node& l, const node& r) {
    return l.l<r.l;
}
namespace _hp {
    int sz=0;
    inline void down() {
        for(int f=2; f<=sz; f<<=1) {
            if(f<sz && hp[f].d<hp[f+1].d) f++;
            if(hp[f].d>hp[f>>1].d) {
                swap(hp[f],hp[f>>1]);
            } else {
                break;
            }
        }
    }
    inline void up() {
        for(int f=sz; f>1; f>>=1) {
            if(hp[f].d>hp[f>>1].d) {
                swap(hp[f],hp[f>>1]);
            } else {
                break;
            }
        }
    }
    inline void hpins(LL l, LL d) {
        sz++;
        hp[sz].l=l, hp[sz].d=d;
        up();
    }
    inline node& hppop() {
        swap(hp[1],hp[sz]);
        sz--;
        down();
        return hp[sz+1];
    }
}
using _hp::hpins;
using _hp::hppop;
node arr[MAXN];
int main() {
#ifdef sahdsg
    freopen("in.txt", "r", stdin);
#endif
	int n; read(n);
	REP(i,0,n) {
        read(arr[i].l); read(arr[i].d); arr[i].l+=arr[i].d;
	}
	sort(arr,arr+n,cmp);
	LL now=0, ans=0;
	REP(i,0,n) {
        hpins(arr[i].l, arr[i].d);
        now+=arr[i].d;
        if(now<=arr[i].l) {
            ans++;
        } else {
            LL d=hppop().d;
            now-=d;
        }
	}
	printf("%lld\n", ans);
	return 0;
}

Gym 101806T Touch The Sky