题解

成功把自己写自闭了

离散化之后再二分我是真不会算坐标啊我这个zz

先离散化所有坐标,然后对于每个位置维护一个最小前驱,然后线段树区间维护最小前驱

什么?位置一样?那就给每个大小为1的位置开个multiset,往上维护的时候就直接左右区间取min

然后就是,在线段树上二分了

我们把正无穷和负无穷位置加进去会比较好维护

如果\((x - m,x + m)\)这个区间不合法,转化为\([x + m,+\infty)\)有前驱在\((-\infty,x - m]\)内

也就意味着我们的距离大小至少是m

在线段树上二分呢,我们找的是这个\(x + m\)在的区间,显然x在右区间就往右区间走

如果x在左区间,那么看看\(mid + 1\)所在的点算出的\(m = pos[mid + 1] - x\)是否满足最小前缀\(mn <= x - m\)

如果满足这个\(x + m\)肯定在右区间

不满足就在左区间

然而,当你二分到一个点的时候,事实上,这个\(x + m\)是可能落在两个坐标中间的,也就是当前节点和当前节点+1,分别计算输出即可

代码

#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define pdi pair<db,int>
#define mp make_pair
#define pb push_back
#define enter putchar('\n')
#define space putchar(' ')
#define eps 1e-8
#define mo 974711
#define MAXN 300005
//#define ivorysi
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
res = 0;char c = getchar();T f = 1;
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 + c - '0';
c = getchar();
}
res *= f;
}
template<class T>
void out(T x) {
if(x < 0) {x = -x;putchar('-');}
if(x >= 10) {
out(x / 10);
}
putchar('0' + x % 10);
}
int N,K,Q;
struct qry_node {
int y,x,t;
friend bool operator < (const qry_node &a,const qry_node &b) {
if(a.y != b.y) return a.y < b.y;
else if(a.t != b.t) return a.t > b.t;
return a.x < b.x;
}
}qry[MAXN * 4];
int qt;
int pos[MAXN],tot,ans[MAXN],cnt[MAXN],hs;
struct node {
int l,r,mq;
}tr[MAXN * 4];
multiset<int> S[MAXN];
multiset<int> T[MAXN * 4];
void update(int u) {
tr[u].mq = min(tr[u << 1].mq,tr[u << 1 | 1].mq);
}
void build(int u,int l,int r) {
tr[u].l = l;tr[u].r = r;
if(l == r) {
tr[u].mq = tot + 1;
if(l == tot) {
tr[u].mq = 1;
for(int i = 1 ; i <= K ; ++i) T[u].insert(1);
}
return;
}
int mid = (l + r) >> 1;
build(u << 1,l,mid);
build(u << 1 | 1,mid + 1,r);
update(u);
}
void Change(int u,int pos,int v) {
if(tr[u].l == tr[u].r) {
if(v > 0) T[u].insert(v);
else T[u].erase(T[u].find(-v));
if(T[u].size() >= 1) tr[u].mq = *T[u].begin();
else tr[u].mq = tot + 1;
return;
}
int mid = (tr[u].l + tr[u].r) >> 1;
if(pos <= mid) Change(u << 1,pos,v);
else Change(u << 1 | 1,pos,v);
update(u);
}
void Query(int u,int x,int suf,int &a) {
if(tr[u].l == tr[u].r) {
int t = min(tr[u].mq,suf);
a = max(a,min(x - pos[t],pos[tr[u].l] - x));
if(tr[u].l < tot) a = max(a,min(x - pos[suf],pos[tr[u].l + 1] - x));
return;
}
int mid = (tr[u].l + tr[u].r) >> 1;
if(x > pos[mid]) {return Query(u << 1 | 1,x,suf,a);}
else {
int t = min(tr[u << 1 | 1].mq,suf);
if(pos[t] > 2 * x - pos[mid + 1]) {
return Query(u << 1,x,min(suf,tr[u << 1 | 1].mq),a);
}
else if(pos[t] <= 2 * x - pos[mid + 1]) {return Query(u << 1 | 1,x,suf,a);}
}
}
void Init() {
read(N);read(K);read(Q);
int x,t,a,b;
for(int i = 1 ; i <= N ; ++i) {
read(x);read(t);read(a);read(b);
qry[++qt] = (qry_node){a,x,t};
qry[++qt] = (qry_node){b + 1,x,-t};
pos[++tot] = x;
}
int l,y;
for(int i = 1 ; i <= Q ; ++i) {
read(l);read(y);
qry[++qt] = (qry_node){y,l,- i - K};
//pos[++tot] = l;
}
pos[++tot] = -1e9;pos[++tot] = 2e9;
sort(qry + 1,qry + qt + 1);
sort(pos + 1,pos + tot + 1);
tot = unique(pos + 1,pos + tot + 1) - pos - 1;
build(1,1,tot);
}
void Solve() {
for(int i = 1 ; i <= K ; ++i) {
S[i].insert(1),S[i].insert(tot);
}
for(int i = 1 ; i <= qt ; ++i) {
int u = qry[i].t; if(u >= -K) {
int x = lower_bound(pos + 1,pos + tot + 1,qry[i].x) - pos;
if(u > 0) {
S[u].insert(x);
auto k = S[u].find(x);
auto g = k,h = k;++g,--h;
if(*g != *k) {
Change(1,*g,*k);Change(1,*g,-(*h));
Change(1,*k,*h);
}
if(cnt[u] == 0 && cnt[u] + 1 == 1) ++hs;
++cnt[u];
}
else {
u = -u;
auto k = S[u].find(x);
auto g = k,h = k;++g,--h;
if(*g != *k) {
Change(1,*g,-(*k));Change(1,*g,*h);
Change(1,*k,-(*h));
}
S[u].erase(k);
if(cnt[u] == 1 && cnt[u] - 1 == 0) --hs;
--cnt[u];
}
}
else {
if(hs != K) ans[- K - u] = -1;
else Query(1,qry[i].x,tot + 1,ans[-K - u]);
}
}
for(int i = 1 ; i <= Q ; ++i) {
out(ans[i]);enter;
}
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
Init();
Solve();
}

【LOJ】#2585. 「APIO2018」新家的更多相关文章

  1. LOJ #2585. 「APIO2018」新家

    #2585. 「APIO2018」新家 https://loj.ac/problem/2585 分析: 线段树+二分. 首先看怎样数颜色,正常的时候,离线扫一遍右端点,每次只记录最右边的点,然后查询左 ...

  2. LOJ 2585 「APIO2018」新家 ——线段树分治+二分答案

    题目:https://loj.ac/problem/2585 算答案的时候要二分! 这样的话,就是对于询问位置 x ,二分出一个最小的 mid 使得 [ x-mid , x+mid ] 里包含所有种类 ...

  3. LOJ #2587「APIO2018」铁人两项

    是不是$ vector$存图非常慢啊...... 题意:求数对$(x,y,z)$的数量使得存在一条$x$到$z$的路径上经过$y$,要求$x,y,z$两两不同  LOJ #2587 $ Solutio ...

  4. LOJ 2586 「APIO2018」选圆圈——KD树

    题目:https://loj.ac/problem/2586 只会 19 分的暴力. y 都相等,仍然按直径从大到小做.如果当前圆没有被删除,那么用线段树把 [ x-r , x+r ] 都打上它的标记 ...

  5. LOJ 2587 「APIO2018」铁人两项——圆方树

    题目:https://loj.ac/problem/2587 先写了 47 分暴力. 对于 n<=50 的部分, n3 枚举三个点,把图的圆方树建出来,合法条件是 c 是 s -> f 路 ...

  6. 【刷题】LOJ 2587 「APIO2018」铁人两项

    题目描述 比特镇的路网由 \(m\) 条双向道路连接的 \(n\) 个交叉路口组成. 最近,比特镇获得了一场铁人两项锦标赛的主办权.这场比赛共有两段赛程:选手先完成一段长跑赛程,然后骑自行车完成第二段 ...

  7. Loj #3056. 「HNOI2019」多边形

    Loj #3056. 「HNOI2019」多边形 小 R 与小 W 在玩游戏. 他们有一个边数为 \(n\) 的凸多边形,其顶点沿逆时针方向标号依次为 \(1,2,3, \ldots , n\).最开 ...

  8. Loj #3055. 「HNOI2019」JOJO

    Loj #3055. 「HNOI2019」JOJO JOJO 的奇幻冒险是一部非常火的漫画.漫画中的男主角经常喜欢连续喊很多的「欧拉」或者「木大」. 为了防止字太多挡住漫画内容,现在打算在新的漫画中用 ...

  9. Loj #2719. 「NOI2018」冒泡排序

    Loj #2719. 「NOI2018」冒泡排序 题目描述 最近,小 S 对冒泡排序产生了浓厚的兴趣.为了问题简单,小 S 只研究对 *\(1\) 到 \(n\) 的排列*的冒泡排序. 下面是对冒泡排 ...

随机推荐

  1. sql server 小技巧 集锦

    sql server 小技巧(1) 导入csv数据到sql server sql server 小技巧(2) 删除sql server中重复的数据 sql server 小技巧(3) SQL Serv ...

  2. sql server 小技巧(6) Cannot resolve the collation conflict between "Latin1_General_CI_AI" and "Chinese_PRC_CI_AS" in the equal to operation

    今天查询二个db,出现这个错误,二种方法,一种是把db里的collation改成一样的:如果不方便可以直接在sql语句后面转一下: select * from table where crm_mscr ...

  3. emWin 工程之汉字显示

    @2018-7-10  工程加入字库后,液晶屏显示非法文字,无法正确显示设置的文字 解决办法 将显示汉字的文件 <MainTask.c> 修改为 UTF-8 格式后显示正常,修改为 ANS ...

  4. SQL Server 事务与隔离级别实例讲解

    上班途中,你在一处ATM机前停了下来.正当你在敲入密码的时候,你的一位家人也正在镇上的另一处TAM机上输入密码.你打算从某个还有500元余额的账户上转出400元,而你的家人想从同一账户取走300元.倘 ...

  5. np.linespace使用方法

    np.linespace用法 觉得有用的话,欢迎一起讨论相互学习~Follow Me 生成指定范围内指定个数的一维数组 def linspace(start, stop, num=50, endpoi ...

  6. HDU 3389 阶梯博弈变形

    n堆石子,每次选取两堆a!=b,(a+b)%2=1 && a!=b && 3|a+b,不能操作者输 选石子堆为奇数的等价于选取步数为奇数的,观察发现 1 3 4 是无法 ...

  7. Linux命令(一)grep查询

    grep -n as test1.txt -n : 显示行号 -v: 显示没有搜索字符的一行 -i:忽视大小写  搜索字符串 模式查找

  8. LVS原理详解(3种工作模式及8种调度算法)

    2017年1月12日, 星期四 LVS原理详解(3种工作模式及8种调度算法)   LVS原理详解及部署之二:LVS原理详解(3种工作方式8种调度算法) 作者:woshiliwentong  发布日期: ...

  9. getopts 用法

    getopts是linux系统中的一个内置变量,一般用在循环中.每当执行循环是,getopts都会检查下一个命令选项,如果这些选项出现在option中,则表示是合法选项,否则不是合法选项.并将这些合法 ...

  10. HDU 3787 A+B 模拟题

    解题报告:就是输入两个用逗号隔开的数字,求出这两个数字的和,并且用正常的方式输出来.直接写一个函数将一个包含逗号的数字转换成十进制的数返回就行了.这里推荐一个函数atoi(),参数是char*型的,然 ...