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);
}