3804. 【NOIP2014模擬8.24】小X 的AK 計劃 (Standard IO)

 

Time Limits: 1000 ms  Memory Limits: 262144 KB  Detailed Limits  

Description

在小X 的家鄉,有機房一條街,街上有很多機房。每個機房裏都有一萬個人在切題。小X 剛刷完CodeChef,準備出來逛逛。
機房一條街有n 個機房,第i 個機房的座標爲xi,小X 的家座標爲0。小X 在街上移動的速度爲1,即從x1 到x2 所耗費的時間爲|x1 − x2|。
每個機房的學生數量不同,ACM 題目水平也良莠不齊。小X 到達第i 個機房後,可以花ti 的時間想題,然後瞬間AK;當然,也可以過機房而不入。
小X 現在只有m 個單位時間,之後他就該趕着去打Codeforces 了。現在他想知道自己最多能在多少個機房AK,希望你幫幫他。

Input

第一行包含兩個整數n;m。
接下來n 行,每行包含兩個整數xi; ti。

Output

第一行包含一個整數,表示小X 最多能AK 的機房數量。

Sample Input

2 10
1 100
5 5

Sample Output

1

Data Constraint

對於30% 的數據,n ≤ 20。
對於60% 的數據,n ≤ 1000。
對於100% 的數據,1 ≤ n ≤ 10^5,0 ≤ m; xi ≤ 10^18,0 ≤ ti ≤ 10^9。

Source / Author: 常州高級中學NOIP2014夏令營 plan

 

總結:

比賽的時候最後打這道題, 想了一個n log ^2 n 的方法, 覺得能過, 就打了。結果tle, 於是我認爲是時間複雜度上過不去, 就打了n log n 的方法, 結果也tle。最後調了才知道(如下圖)

左右都能走的情況, 我左右都遍歷, 這不是傻嗎, 活活遍歷了整一棵數。

板子要記清楚。

題解 : 

對於已經確定要走的幾個機房, 肯定是根據x座標從左往右走最優。

於是我們枚舉最遠走到那個機房。

然後log n求答案。

O(n log n) CODE

#include<bits/stdc++.h>
#define open(x) freopen(x".in", "r", stdin);freopen(x".out", "w", stdout)
#define mem(a, b) memset(a, b, sizeof(a))
#define mcy(a, b) memcpy(a, b, sizeof(a))
#define pf printf
#define sf scanf
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#define fo(i, a, b) for( ll i = a; i <= b; ++i) 
#define fown(i, a, b) for( ll i = a; i >= b; --i)
#define em(p, x) for(ll p=tail[x];p;p=e[p].fr)
#define ll long long
#define wt(a, c, d, s) fo(i, c, d) pf((s), a[i]); puts("")
#define rd(a, c, d) fo(iii, c, d) in((a)[i])
#define N 200010
#define inf 2147483647
#define mod (ll)(1e9 + 7)
#define maxn (1e9+1)
using namespace std;

template<class T> 
T in(T &x) {
	x=0;
	char ch = getchar(); ll f = 0;
	while(ch < '0' || ch > '9') f |= ch == '-', ch = getchar();
	while(ch >= '0' && ch <= '9') x = (x<<1) + (x<<3) + ch - '0', ch = getchar();
	x = f ? -x : x;
	return x;
}

struct cre {
	ll v, id;
}b[N];
bool cmpcre(cre a, cre b) {return a.v < b.v;}

struct room {
	ll pos, t;
}a[N];


ll n, m, ans;

#define ls k << 1, l, mid
#define rs k << 1 | 1, mid + 1, r
ll num[N * 4], SUM[N * 4], Fo[N];

void insert(ll k, ll l, ll r, ll t) {
	++num[k];
	if(l == r) 
	{
		SUM[k] += Fo[l];
		return ;
	}
	ll mid = l + r >> 1;
	if(t <= mid) insert(ls, t); else insert(rs, t);
	
	SUM[k] = SUM[k << 1] + SUM[k <<1 | 1];
	
	return ;
}

ll query(ll k, ll l, ll r, ll p) { // sum = p
	
	if(p == 0) return 0;
	if(l == r) {
		if(Fo[l] == 0 ) {
			return num[k];
		}
		return min(p / Fo[l], num[k]);
	}
	
	ll mid = l + r >> 1;
	
	ll sumls = SUM[k << 1], sumrs = SUM[k << 1 | 1];
	if(sumls >= p) return query(ls, p); else {
		return num[k << 1]+ query(rs, p - sumls);
	}
}

void init() {
	fo(i, 1, n) b[i] = (cre){a[i].t, i};
	
	sort(b + 1, b + 1 + n, cmpcre);
	b[0].v = -1;
	for(ll cnt = 0, i = 1; i <= n ; ++i) {
		if(b[i].v != b[i - 1].v)++cnt;
		Fo[cnt] = a[b[i].id].t;
		a[b[i].id].t = cnt;
	}
}

void work() {
	fo(i, 1, n) {
		ll Far = a[i].pos, rem = m - Far;
		insert(1, 1, n, a[i].t); //after cre
		if(rem <= 0) continue;
		ll tmp = query(1ll, 1ll, n, rem);
		ans = max(ans, tmp);
		
	}
}
bool cmp(room a, room b) {return a.pos < b.pos;}
int main() {
	in(n), in(m);
	
	fo(i, 1, n) in(a[i].pos), in(a[i].t);
	
	sort(a + 1, a + 1 + n, cmp);
	
	init();
	
	work();
	
	pf("%lld\n", ans);
}

O(n log n)

 

O(N log ^2 n) CODE

 

#include<bits/stdc++.h>
#define open(x) freopen(x".in", "r", stdin);freopen(x".out", "w", stdout)
#define mem(a, b) memset(a, b, sizeof(a))
#define mcy(a, b) memcpy(a, b, sizeof(a))
#define pf printf
#define sf scanf
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#define fo(i, a, b) for( ll i = a; i <= b; ++i) 
#define fown(i, a, b) for( ll i = a; i >= b; --i)
#define em(p, x) for(ll p=tail[x];p;p=e[p].fr)
#define ll long long
#define wt(a, c, d, s) fo(i, c, d) pf((s), a[i]); puts("")
#define rd(a, c, d) fo(iii, c, d) in((a)[i])
#define N 100010
#define inf 2147483647
#define mod (ll)(1e9 + 7)
#define maxn (1e9+1)
using namespace std;

template<class T> 
T in(T &x) {
	x=0;
	char ch = getchar(); ll f = 0;
	while(ch < '0' || ch > '9') f |= ch == '-', ch = getchar();
	while(ch >= '0' && ch <= '9') x = (x<<1) + (x<<3) + ch - '0', ch = getchar();
	x = f ? -x : x;
	return x;
}

struct cre {
	ll v, id;
}b[N];
bool cmpcre(cre a, cre b) {return a.v < b.v;}

struct room {
	ll pos, t;
}a[N];


ll n, m, ans;

#define ls k << 1, l, mid
#define rs k << 1 | 1, mid + 1, r
ll num[N * 4], SUM[N * 4], Fo[N];

void insert(ll k, ll l, ll r, ll t) {
	++num[k];
	if(l == r) 
	{
		SUM[k] += Fo[l];
		return ;
	}
	ll mid = l + r >> 1;
	if(t <= mid) insert(ls, t); else insert(rs, t);
	
	SUM[k] = SUM[k << 1] + SUM[k <<1 | 1];
	
	return ;
}

ll query(ll k, ll l, ll r, ll p) { // pre p small
	
	if(l == r) {
		int use = min(p, num[k]);
		return Fo[l] * use;
	}
	
	ll mid = l + r >> 1;
	
	ll numls = num[k << 1], numrs = num[k << 1 | 1];
	if(numls >= p) return query(ls, p); else {
		return SUM[k << 1] + query(rs, p - numls);
	}
}

void init() {
	fo(i, 1, n) b[i] = (cre){a[i].t, i};
	
	sort(b + 1, b + 1 + n, cmpcre);
	b[0].v = -1;
	for(ll cnt = 0, i = 1; i <= n ; ++i) {
		if(b[i].v != b[i - 1].v)++cnt;
		Fo[cnt] = a[b[i].id].t;
		a[b[i].id].t = cnt;
	}
}

ll check(ll mid, ll rem) {
	ll sum = query(1, 1, n, mid); //sum(rank-1 , rank mid)
	if(sum > rem) return 0;
	return 1;
}

void work() {
	fo(i, 1, n) {
		ll Far = a[i].pos, rem = m - Far;
		insert(1, 1, n, a[i].t); //after cre
		if(rem <= 0) continue;
		
		ll l = 0, r = i, mid = 0;
		while(l <= r) {
			mid = l + r >> 1;
			if(mid == 76001)
			{
				mid = 76001;
				l = l;
				r = r;
			}
			if(check(mid, rem)) {
				ans = max(ans, mid);
				l = mid + 1;
			} else r = mid - 1;
		}
	
	}
}
bool cmp(room a, room b) {return a.pos < b.pos;}
int main() {
	open("AK");
	in(n), in(m);
	
	fo(i, 1, n) in(a[i].pos), in(a[i].t);
	
	sort(a + 1, a + 1 + n, cmp);
	
	init();
	
	work();
	
	pf("%lld\n", ans);
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章