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