LG-P8858 折线 题解
LG-P8858 折线 Solution
更好的阅读体验戳此进入
题面
从从
Solution
提供一个
首先我们可以考虑观察一下样例和大样例,不难发现所有答案均在
首先一个折点的话一定无法将矩形分为两块,所以不合法。
两个折点的话即为通过一条直线将矩形分为两半,这条直线可以水平也可以竖直,所以对于这种情况,我们只需要对
三个折点的话随便画一下就会发现,最终的情况一定是隔离起来一个左上角或者右下角,如图:
考虑如何维护,显然可以把这个东西按照类似二位偏序或者说二维数点来写,先按照
如果以上的判断都不合法的话那么显然最终答案即为
显然这个时候我们是可以隔离出来任意数量的整点了,比较好理解,考虑一下如果想更多地包含新的点,将中间那块凸起略移动一下
至此我们便以
赛时 Code
#define _USE_MATH_DEFINES
#include <bits/stdc++.h>
#define PI M_PI
#define E M_E
#define npt nullptr
#define SON i->to
#define OPNEW void* operator new(size_t)
#define ROPNEW(arr) void* Edge::operator new(size_t){static Edge* P = arr; return P++;}
using namespace std;
mt19937 rnd(random_device{}());
int rndd(int l, int r){return rnd() % (r - l + 1) + l;}
bool rnddd(int x){return rndd(1, 100) <= x;}
typedef unsigned int uint;
typedef unsigned long long unll;
typedef long long ll;
typedef long double ld;
#define MAXN (510000)
template< typename T = int >
inline T read(void);
int N;
struct Coord{int x, y;}a[MAXN];
int bucx[MAXN], bucy[MAXN];
class SegTree{
private:
int tr[MAXN << 2];
#define LS (p << 1)
#define RS (LS | 1)
#define MID ((gl + gr) >> 1)
public:
void Clear(int p = 1, int gl = 1, int gr = N + 1){
if(gl == gr)return tr[p] = 0, void();
Clear(LS, gl, MID);
Clear(RS, MID + 1, gr);
tr[p] = 0;
}
void Pushup(int p){tr[p] = tr[LS] + tr[RS];}
void Modify(int idx, int v = 1, int p = 1, int gl = 1, int gr = N + 1){
if(gl == gr)return tr[p] += v, void();
if(idx <= MID)Modify(idx, v, LS, gl, MID);
else Modify(idx, v, RS, MID + 1, gr);
Pushup(p);
}
bool QueryR(int val, int cur = 0, int p = 1, int gl = 1, int gr = N + 1){
// printf("Querying %d ~ %d, cur = %d\n", gl, gr, cur);
if(cur + tr[p] == val)return true;
if(gl == gr)return false;
if(cur + tr[LS] >= val)return QueryR(val, cur, LS, gl, MID);
else return QueryR(val, cur + tr[LS], RS, MID + 1, gr);
}
bool QueryL(int val, int cur = 0, int p = 1, int gl = 1, int gr = N + 1){
// printf("Querying %d ~ %d, cur = %d\n", gl, gr, cur);
if(cur + tr[p] == val)return true;
if(gl == gr)return false;
if(cur + tr[RS] >= val)return QueryL(val, cur, RS, MID + 1, gr);
else return QueryL(val, cur + tr[RS], LS, gl, MID);
}
}st;
int main(){
// freopen("ex_line2.in", "r", stdin);
// freopen("out.txt", "w", stdout);
int T = read();
while(T--){
bool flag(false);
memset(bucx, 0, sizeof(int) * (N + 10)), memset(bucy, 0, sizeof(int) * (N + 10));
N = read();
for(int i = 1; i <= N; ++i)
a[i].x = read() + 1, a[i].y = read() + 1, bucx[a[i].x]++, bucy[a[i].y]++;
a[N + 1].x = a[N + 1].y = 0;
for(int i = 1; i <= N; ++i){
bucx[i] += bucx[i - 1], bucy[i] += bucy[i - 1];
if(bucx[i] == N >> 1 || bucy[i] == N >> 1){printf("2\n"), flag = true; break;}
}if(flag)continue;
sort(a + 1, a + N + 1, [](const Coord &a, const Coord &b)->bool{return a.x == b.x ? a.y < b.y : a.x < b.x;});
st.Clear();
for(int i = N; i >= 1; --i){
st.Modify(a[i].y);
while(a[i - 1].x == a[i].x)st.Modify(a[--i].y);
if(st.QueryR(N / 2)){printf("3\n"), flag = true; break;}
}if(flag)continue;
st.Clear();
for(int i = 1; i <= N; ++i){
st.Modify(a[i].y);
while(a[i + 1].x == a[i].x)st.Modify(a[++i].y);
if(st.QueryL(N / 2)){printf("3\n"), flag = true; break;}
}if(flag)continue;
printf("4\n");
}
fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
return 0;
}
template < typename T >
inline T read(void){
T ret(0);
int flag(1);
char c = getchar();
while(c != '-' && !isdigit(c))c = getchar();
if(c == '-')flag = -1, c = getchar();
while(isdigit(c)){
ret *= 10;
ret += int(c - '0');
c = getchar();
}
ret *= flag;
return ret;
}
UPD
update-2022_11_22 初稿
update-2022_11_22 修改了一处细节错误
update-2022_11_23 图片被洛谷墙了,换成了洛谷图床
本文作者:Tsawke
本文链接:https://www.cnblogs.com/tsawke/p/16945704.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步