题解:P11255 [GDKOI2023 普及组] 淋雨
Claire0918 · · 题解
首先将所有雨点转化为
我们将绝对值拆开,即要求
这是一个经典的三维偏序问题,直接使用 CDQ 分治即可做到
Code:
#include<bits/stdc++.h>
#define mem(a, v) memset(a, v, sizeof(a))
using namespace std;
namespace IO{
#define SIZ (1 << 18)
char ibuf[SIZ], *p1 = nullptr, *p2 = nullptr;
#define gc() (p1 == p2 && (p2 = (p1 = ibuf) + fread(ibuf, 1, SIZ, stdin), p1 == p2) ? EOF : *p1++)
template <typename tp>
void rd(tp &x){
x = 0;
int f = 1;
char c = gc();
for (;!isdigit(c); c == '-' && (f = -1), c = gc());
for (;isdigit(c); x = x * 10 + (c ^ 48), c = gc());
x *= f;
}
template <typename tp, typename... Arg>
inline void rd(tp &x, Arg &...args){
rd(x), rd(args...);
}
char obuf[SIZ], *p3 = obuf;
inline void flush(){
fwrite(obuf, 1, p3 - obuf, stdout), p3 = obuf;
}
inline void pc(const char c){
p3 - obuf == SIZ && (flush(), 1538), *p3++ = c;
}
template <typename tp>
void prt(tp x, char ed = '\n'){
x < 0 && (pc('-'), x = -x);
static char stk[40];
int stkp = 0;
do{
stk[stkp] = char(x % 10), x /= 10, ++stkp;
} while (x);
while (stkp){
pc(char(stk[--stkp] + '0'));
}
pc(ed);
}
#undef gc
#undef SIZ
}
using namespace IO;
const int maxn = 5e5 + 10, maxq = 5e5 + 10;
struct Val{
long long x, y;
int f;
constexpr Val(long long x = 0, long long y = 0, int f = 0): x(x), y(y), f(f){}
} a[maxn];
int n, q, s, v, k;
int res[maxq];
vector<long long> tmp;
vector<pair<int, long long> > qry[maxn];
namespace segtree{
int tree[maxn];
inline int lbw(int x){
return x & -x;
}
inline void add(int x, int k, int len){
for (;x <= len; tree[x] = max(tree[x], k), x += lbw(x));
}
inline int query(int x){
int res = 0;
for (;x; res = max(res, tree[x]), x -= lbw(x));
return res;
}
}
using namespace segtree;
inline int pos(int x){
return lower_bound(tmp.begin(), tmp.end(), a[x].y - k * a[x].x) - tmp.begin() + 1;
}
inline void solve(int l, int r){
if (l == r){
return a[l].f = max(a[l].f, 1), void();
}
const int mid = l + r >> 1;
const auto cmp = [&](Val x, Val y){return x.y + k * x.x > y.y + k * y.x;};
solve(l, mid), sort(a + l, a + mid + 1, cmp), sort(a + mid + 1, a + r + 1, cmp);
tmp.clear();
for (int i = l; i <= r; i++){
tmp.push_back(a[i].y - k * a[i].x);
}
sort(tmp.begin(), tmp.end()), unique(tmp.begin(), tmp.end());
for (int i = 0; i <= tmp.size(); tree[i++] = 0);
for (int i = mid + 1, p = l; i <= r; i++){
for (;p <= mid && a[p].y + k * a[p].x >= a[i].y + k * a[i].x; add(pos(p), a[p].f, tmp.size()), p++);
a[i].f = max(a[i].f, query(pos(i)) + 1);
}
sort(a + mid + 1, a + r + 1, [](Val x, Val y){return x.x > y.x || x.x == y.x && x.y < y.y;}), solve(mid + 1, r);
}
int main(){
rd(n, q, s, v, k);
for (int i = 1; i <= n; i++){
long long x, y;
rd(x, y), a[i] = Val(y, x * s + y * v, 0);
}
sort(a + 1, a + n + 1, [](Val x, Val y){return x.x > y.x || x.x == y.x && x.y < y.y;}), solve(1, n);
sort(a + 1, a + n + 1, [](Val x, Val y){return x.y + k * x.x > y.y + k * y.x;});
for (int i = 1; i <= q; i++){
long long x;
rd(x), x *= s;
int l = 1, r = n;
while (l < r){
const int mid = l + r + 1 >> 1;
if (x <= a[mid].y + k * a[mid].x){
l = mid;
}else{
r = mid - 1;
}
}
x <= a[l].y + k * a[l].x && (qry[l].push_back(make_pair(i, x)), 1538);
}
for (int i = 1; i <= n; i++){
tmp.push_back(a[i].y - k * a[i].x);
}
sort(tmp.begin(), tmp.end()), unique(tmp.begin(), tmp.end());
for (int i = 1; i <= tmp.size(); tree[i++] = 0);
for (int i = 1; i <= n; i++){
add(pos(i), a[i].f, tmp.size());
for (auto x: qry[i]){
const int p = upper_bound(tmp.begin(), tmp.end(), x.second) - tmp.begin();
p && (res[x.first] = query(p));
}
}
for (int i = 1; i <= q; i++){
prt(res[i]);
}
flush();
return 0;
}
但是我们有
Code:
#include<bits/stdc++.h>
#define mem(a, v) memset(a, v, sizeof(a))
using namespace std;
const int maxn = 5e5 + 10, maxq = 5e5 + 10;
struct Val{
long long x, y;
int f;
constexpr Val(long long x = 0, long long y = 0, int f = 0): x(x), y(y), f(f){}
} a[maxn];
int n, q, s, v, k;
int res[maxq];
vector<long long> tmp;
vector<pair<int, long long> > qry[maxn];
namespace BIT{
int tree[maxn];
inline int lbw(int x){
return x & -x;
}
inline void add(int x, int k){
for (;x <= tmp.size(); tree[x] = max(tree[x], k), x += lbw(x));
}
inline int query(int x){
int res = 0;
for (;x; res = max(res, tree[x]), x -= lbw(x));
return res;
}
}
using namespace BIT;
inline int pos(int x){
return lower_bound(tmp.begin(), tmp.end(), a[x].y - k * a[x].x) - tmp.begin() + 1;
}
int main(){
scanf("%d %d %d %d %d", &n, &q, &s, &v, &k);
for (int i = 1; i <= n; i++){
long long x, y;
scanf("%lld %lld", &x, &y), a[i] = Val(y, x * s + y * v, 0), tmp.push_back(a[i].y - k * a[i].x);
}
sort(tmp.begin(), tmp.end()), unique(tmp.begin(), tmp.end()), sort(a + 1, a + n + 1, [](Val x, Val y){return x.y + k * x.x > y.y + k * y.x;});
for (int i = 1; i <= q; i++){
long long x;
scanf("%lld", &x), x *= s;
int l = 1, r = n;
while (l < r){
const int mid = l + r + 1 >> 1;
if (x <= a[mid].y + k * a[mid].x){
l = mid;
}else{
r = mid - 1;
}
}
x <= a[l].y + k * a[l].x && (qry[l].push_back(make_pair(i, x)), 1538);
}
for (int i = 1; i <= n; i++){
a[i].f = query(pos(i)) + 1, add(pos(i), a[i].f);
for (auto x: qry[i]){
const int p = upper_bound(tmp.begin(), tmp.end(), x.second) - tmp.begin();
p && (res[x.first] = query(p));
}
}
for (int i = 1; i <= q; i++){
printf("%d\n", res[i]);
}
return 0;
}