【题目大意】

给出平面上$n$个点$(x_i, y_i)$,请选择一个不在这$n$个点之内的点$(X, Y)$,定义$(X, Y)$的价值为往上下左右四个方向射出去直线,经过$n$个点中的数量的最小值。

Task 1: 求价值最大的点

Task 2: 求价值最大的点的个数

保证Task 1和Task 2各占50pts。

对于30%的数据,$n \leq 200$;

对于60%的数据,$n \leq 5000$;

对于100%的数据,$n \leq 300000$。

每档数据中,50%保证$1 \leq x_i, y_i \leq n$;50%保证$1 \leq x_i, y_i \leq 10^9$。

【题解】

考场写了60分暴力。。签到题不会打系列。

回家路上认真想了想,离散后把每个位置用vector存起来。

二分答案$x$,那么得到的就是若干合法区间(有横的也有竖的),那么一个点只要被一横一竖两个区间同时经过,就有1的贡献,先不考虑$(X, Y)$在$n$个点中的情况,那么这样就能用扫描线+BIT解决了。

预处理出来对于关键点的贡献,统计的时候减去即可。

复杂度$O(nlog^2n)$。

Orz YangPKU

# include <vector>
# include <stdio.h>
# include <assert.h>
# include <string.h>
# include <iostream>
# include <algorithm>
// # include <bits/stdc++.h> using namespace std; typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const int M = 3e5 + ;
const int mod = 1e9+; inline int getint() {
int x = ; char ch = getchar();
while(!isdigit(ch)) ch = getchar();
while(isdigit(ch)) x = (x<<) + (x<<) + ch - '', ch = getchar();
return x;
} int n, x[M], y[M], X, Y, ori[M];
vector<int> psa, psb;
vector<int> vx[M], vy[M]; int xlen[M], ylen[M]; struct option {
int op, x, yl, yr, del;
option() {}
option(int op, int x, int yl, int yr, int del = ) : op(op), x(x), yl(yl), yr(yr), del(del) {}
friend bool operator < (option a, option b) {
return a.x < b.x || (a.x == b.x && a.op < b.op);
}
}o[M * ]; int on; struct BIT {
# define lb(x) (x&(-x))
ll c[M]; int n;
inline void set(int _n) {
n = _n; memset(c, , sizeof c);
}
inline void edt(int x, int d) {
for (; x<=n; x+=lb(x)) c[x] += d;
}
inline ll sum(int x) {
ll ret = ;
for (; x; x-=lb(x)) ret += c[x];
return ret;
}
inline ll sum(int x, int y) {
if(x > y) return ;
return sum(y) - sum(x-);
}
# undef lb
}T; inline ll chk(int x) {
ll ans = ;
on = ;
for (int i=, l, r; i<=X; ++i) {
if(xlen[i] >= x + x) {
l = vx[i][x-] + , r = vx[i][xlen[i]-x] - ;
o[++on] = option(, i, l, r);
}
}
for (int i=, l, r; i<=Y; ++i) {
if(ylen[i] >= x + x) {
l = vy[i][x-] + , r = vy[i][ylen[i]-x] - ;
o[++on] = option(, l, i, i, );
o[++on] = option(, r+, i, i, -);
}
}
sort(o+, o+on+);
for (int i=; i<=on; ++i) {
if(o[i].op == ) T.edt(o[i].yl, o[i].del);
else ans += T.sum(o[i].yl, o[i].yr);
}
for (int i=; i<=n; ++i) ans -= (ori[i] >= x);
return ans;
} int main() {
int type;
n = getint(); type = getint();
for (int i=; i<=n; ++i) psa.push_back(x[i] = getint()), psb.push_back(y[i] = getint());
sort(psa.begin(), psa.end()); psa.erase(unique(psa.begin(), psa.end()), psa.end()); X = psa.size();
sort(psb.begin(), psb.end()); psb.erase(unique(psb.begin(), psb.end()), psb.end()); Y = psb.size();
for (int i=; i<=n; ++i) x[i] = lower_bound(psa.begin(), psa.end(), x[i]) - psa.begin() + , y[i] = lower_bound(psb.begin(), psb.end(), y[i]) - psb.begin() + ;
for (int i=; i<=n; ++i) vx[x[i]].push_back(y[i]), vy[y[i]].push_back(x[i]);
for (int i=; i<=X; ++i) {
sort(vx[i].begin(), vx[i].end());
xlen[i] = vx[i].size();
}
for (int i=; i<=Y; ++i) {
sort(vy[i].begin(), vy[i].end());
ylen[i] = vy[i].size();
}
for (int i=, xid, yid; i<=n; ++i) {
xid = lower_bound(vy[y[i]].begin(), vy[y[i]].end(), x[i]) - vy[y[i]].begin();
yid = lower_bound(vx[x[i]].begin(), vx[x[i]].end(), y[i]) - vx[x[i]].begin();
ori[i] = min(min(xid, ylen[y[i]]-xid-), min(yid, xlen[x[i]]-yid-));
}
int l = , r = n/, mid, ans = -; T.set(Y); ll t;
while() {
if(r - l <= ) {
for (int i=r; i>=l; --i) {
if(t = chk(i)) {
ans = i;
break;
}
}
break;
}
mid = l+r>>;
if(chk(mid)) l = mid;
else r = mid;
}
assert(ans != -);
if(type == ) printf("%d\n", ans);
else printf("%lld\n", t);
return ;
}

省队集训 Day3 杨北大的更多相关文章

  1. 省队集训Day3 light

    [问题描述] “若是万一琪露诺(俗称 rhl)进行攻击,什么都好,冷静地回答她的问题来吸引她.对方表现出兴趣的话,那就慢慢地反问.在她考虑答案的时候,趁机逃吧.就算是很简单的问题,她一定也答不上来.” ...

  2. 省队集训Day3 tree

    [题目描述] RHL 有一天看到 lmc 在玩一个游戏. “愚蠢的人类哟,what are you doing”,RHL 说. “我在玩一个游戏.现在这里有一个有 n 个结点的有根树,其中有 m 个叶 ...

  3. bzoj4171 or 省队集训day3 chess: Rhl的游戏

    [题目描述] RHL最近迷上一个小游戏:Flip it.游戏的规则很简单,在一个N*M的格子上,有一些格子是黑色,有一些是白色.每选择一个格子按一次,格子以及周围边相邻的格子都会翻转颜色(边相邻指至少 ...

  4. FJ省队集训DAY3 T2

    思路:如果一个DAG要的路径上只要一条边去切掉,那么要怎么求?很容易就想到最小割,但是如果直接做最小割会走出重复的部分,那我们就这样:反向边设为inf,这样最小割的时候就不会割到了,判断无解我们直接用 ...

  5. FJ省队集训DAY3 T1

    思路:我们考虑如果取掉一个部分,那么能影响到最优解的只有离它最近的那两个部分. 因此我们考虑堆维护最小的部分,离散化离散掉区间,然后用线段树维护区间有没有雪,最后用平衡树在线段的左右端点上面维护最小的 ...

  6. 省队集训 Day3 吴清华

    [题目大意] 给网格图,共有$n * n$个关键节点,横向.纵向距离均为$d$,那么网格总长度和宽度均为$(n+1) * d + 1$,最外围一圈除了四角是终止节点.要求每个关键节点都要通过线连向终止 ...

  7. 省队集训 Day3 陈姚班

    [题目大意] 给一张网格图,上往下有流量限制,下往上没有,左往右有流量限制. $n * m \leq 2.5 * 10^6$ [题解] 考场直接上最大流,50分.竟然傻逼没看出狼抓兔子. 平面图转对偶 ...

  8. JS省队集训记

    不知不觉省队集训已经结束,离noi也越来越近了呢 论考前实战训练的重要性,让我随便总结一下这几天的考试 Day 1 T1 唉,感觉跟xj测试很像啊?meet in middle,不过这种题不多测是什么 ...

  9. HN2018省队集训

    HN2018省队集训 Day1 今天的题目来自于雅礼的高二学长\(dy0607\). 压缩包下载 密码: 27n7 流水账 震惊!穿着该校校服竟然在四大名校畅通无阻?霸主地位已定? \(7:10\)从 ...

随机推荐

  1. (十一)instanceof 和 getclass 的区别

    判断两个对象是否为同一类型,时常用到getclass 和 instanceof ,而这两个函数又是时常让人混淆.下面从一个例子说明两者的区别: public class Test_drive { pu ...

  2. Github Atom汉化方式

    1.下载:Atom  https://atom.io/ 2.安装 3.菜单栏 -- Setting --- Install --- 搜索Chinese --安装汉化包 4.重启 生效.

  3. matlab如何将数组中的NAN值去除

        比如我们一组数据,里面有不少的NaN值,如何将其删除掉呢?可以通过find函数来搞定.     我们可以通过importdata('data.txt')将数据文件data.txt导入数组A中. ...

  4. tcp中的发送窗口是啥意思?

    初始的三次握手: 02:52:36.585412 IP 127.0.0.1.59764 > 127.0.0.1.8000: Flags [S], seq 3800457532, win 4369 ...

  5. Sparse autoencoder implementation 稀疏自编码器实现

    任务:在这个问题中,你将实现稀疏自编码器算法,并且展示它怎么发现边缘是自然图像的一个好的表示. 在文件 sparseae_exercise.zip中,我们已经提供了一些Matlab中的初始代码,你应该 ...

  6. 响应式布局(rem布局),使用JS动态设置fontsize

    var cw = document.documentElement.clientWidth; if (cw > 1920) { cw = 1920; } document.getElements ...

  7. P1278 单词游戏

    题目描述 Io和Ao在玩一个单词游戏. 他们轮流说出一个仅包含元音字母的单词,并且后一个单词的第一个字母必须与前一个单词的最后一个字母一致. 游戏可以从任何一个单词开始. 任何单词禁止说两遍,游戏中只 ...

  8. VS2017常用快快捷键

    VS2017常用快快捷键 VS中代码对齐等快捷键        在VS中,选定代码后,按Ctrl+K+F组合键,可以自动进行代码对齐.        注意:要先按下Ctrl和K,再按下F,因为Ctrl ...

  9. 一些技巧 && 常数优化 && 出现の错误

    开坑原因 7.21 今天DTZ大爷教了我一个算欧拉函数的好方法......是质因数复杂度的 这让我想到,这些小技巧小idea,很多时候,可能就是考场上最致命.最一击必杀的"大招" ...

  10. BZOJ1604 & 洛谷2906:[USACO2008 OPEN]Cow Neighborhoods 奶牛的邻居——题解

    http://www.lydsy.com/JudgeOnline/problem.php?id=1604 https://www.luogu.org/problemnew/show/P2906#sub ...