「LOJ 2585」「APIO2018」新家

LOJ #2585

题意

在数轴上有\(n\)家商店,第\(i\)个商店有坐标\(x_i\),种类\(t_i\in[1..k]\),出现时间\([a_i,b_i]\)

\(q\)组询问\(l_i,y_i\),表示询问在时间\(y_i\),离坐标\(l_i\)最远的商店类型到\(l_i\)的距离

类型\(t\)的商店到一个点的距离定义为所有存在的\(t\)类商店到这个点的距离的最大值

\(1\le n,q\le 3*10^5,1\le k\le n\)

\(1\le x_i,a_i,b_i\le 10^9\)

\(1\le l_i,y_i\le 10^8\)


分析

参考kczno1的这题的一个log做法

感觉说得不能再清楚了..

每种店开一个\(multiset\)维护前驱,每个坐标开一个支持删除的堆维护这个位置的最小前驱

新开一个坐标\(inf\)的点把所有店放上面

全部值都可以离散化


代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#include<cstdio>
#include<algorithm>
#include<ctype.h>
#include<string.h>
#include<math.h>
#include<set>
#include<queue>

using namespace std;
#define ll long long

inline char read() {
static const int IN_LEN = 1000000;
static char buf[IN_LEN], *s, *t;
return (s == t ? t = (s = buf) + fread(buf, 1, IN_LEN, stdin), (s == t ? -1 : *s++) : *s++);
}
template<class T>
inline void read(T &x) {
static bool iosig;
static char c;
for (iosig = false, c = read(); !isdigit(c); c = read()) {
if (c == '-') iosig = true;
if (c == -1) return;
}
for (x = 0; isdigit(c); c = read()) x = ((x + (x << 2)) << 1) + (c ^ '0');
if (iosig) x = -x;
}
const int OUT_LEN = 10000000;
char obuf[OUT_LEN], *ooh = obuf;
inline void print(char c) {
if (ooh == obuf + OUT_LEN) fwrite(obuf, 1, OUT_LEN, stdout), ooh = obuf;
*ooh++ = c;
}
template<class T>
inline void print(T x) {
static int buf[30], cnt;
if (x == 0) print('0');
else {
if (x < 0) print('-'), x = -x;
for (cnt = 0; x; x /= 10) buf[++cnt] = x % 10 + 48;
while (cnt) print((char)buf[cnt--]);
}
}
inline void flush() { fwrite(obuf, 1, ooh - obuf, stdout); }

const int N = 300005;
int k, n, m, cnt, Id, tot, ori[N], Ans[N], f[N], mn[N<<2];
pair<int,int*> disc[N<<1];
multiset<int> s[N];
struct opt{
int x, t, ti;
inline bool operator <(const opt &rhs)const{ return ti<rhs.ti;}
}a[N<<1];
struct que{
int ti, x, id;
inline bool operator <(const que &rhs)const{ return ti<rhs.ti;}
}q[N];
struct heap{
priority_queue<int,vector<int>,greater<int>> a, b;
inline void ins(int x){ a.push(x);}
inline void del(int x){
if(x!=a.top()) b.push(x);
else{
a.pop();
while(b.size() && a.top()==b.top()) a.pop(), b.pop();
}
}
}h[N];

void build(int l, int r, int t){
if(l==r){
h[l].ins(Id);
if(l==Id) for(int i=1; i<=k; ++i) h[l].ins(0);
mn[t]=h[l].a.top();
return;
}
int mid=l+r>>1, k=t<<1;
build(l, mid, k), build(mid+1, r, k|1);
mn[t]=min(mn[k], mn[k|1]);
}
void modify(int l, int r, int t, int x){
if(l==r) return (void)(mn[t]=h[l].a.top());
int mid=l+r>>1, k=t<<1;
if(x<=mid) modify(l, mid, k, x); else modify(mid+1, r, k|1, x);
mn[t]=min(mn[k], mn[k|1]);
}
int query(int l, int r, int t, int x, int now=1e9){
if(l==r) return min(ori[l]-x, x-min(now, ori[mn[t]]));
int mid=l+r>>1, k=t<<1;
if(x>ori[mid]) return query(mid+1, r, k|1, x, now);
if(ori[mid]+1+min(now, ori[mn[k|1]])<=x*2) return query(mid+1, r, k|1, x, now);
else return query(l, mid, k, x, min(now, ori[mn[k|1]]));
}
inline void work(int x, int t){
if(t>0){
tot+=!f[t]++;
auto it=s[t].lower_bound(x);
h[x].ins(it==s[t].begin()?0:(--it, *it++)), modify(1, Id, 1, x);
if(it!=s[t].end()){
int y=*it;
h[y].del(it==s[t].begin()?0:(--it, *it++)), h[y].ins(x);
modify(1, Id, 1, y);
}
s[t].insert(x);
}
else{
t=-t;
tot-=!--f[t];
auto it=s[t].find(x);
h[x].del(it==s[t].begin()?0:(--it, *it++)), modify(1, Id, 1, x);
s[t].erase(it++);
if(it!=s[t].end()){
int y=*it;
h[y].del(x), h[y].ins(it==s[t].begin()?0:*--it);
modify(1, Id, 1, y);
}
}
}
int main() {
read(n), read(k), read(m);
for(int i=0; i<n; ++i){
static int x, t, l, r;
read(x), read(t), read(l), read(r);
a[cnt++]=(opt){x, t, l}, a[cnt++]=(opt){x, t, r+1};
}

for(int i=0; i<cnt; ++i) disc[i]=make_pair(a[i].t, &a[i].t);
sort(disc, disc+cnt);
for(int i=0, id=1; i<cnt; ++i)
*(disc[i].second)=(i && disc[i].first!=disc[i-1].first?++id:id);
for(int i=0; i<cnt; ++i) disc[i]=make_pair(a[i].x, &a[i].x);
sort(disc, disc+cnt);
Id=1;
for(int i=0; i<cnt; ++i)
ori[*(disc[i].second)=(i && disc[i].first!=disc[i-1].first?++Id:Id)]=disc[i].first;
ori[0]=-1e9, ori[++Id]=1e9;
for(int i=1; i<cnt; i+=2) a[i].t=-a[i].t;

build(1, Id, 1);
for(int i=1; i<=k; ++i) s[i].insert(Id);
sort(a, a+cnt);
for(int i=0; i<m; ++i) read(q[i].x), read(q[i].ti), q[i].id=i;
sort(q, q+m);
int j=0;
for(int i=0; i<m; ++i){
while(a[j].ti<=q[i].ti && j<cnt) work(a[j].x, a[j].t), ++j;
Ans[q[i].id]=(tot==k?query(1, Id, 1, q[i].x):-1);
}
for(int i=0; i<m; ++i) print(Ans[i]), print('\n');
return flush(), 0;
}
0%