[Codeforces Round #665 (Div. 2)] E. Divide Square (线段树,扫描线求交点)
题面:
题意:
给定一个左下角和右上角分别是((0,0),(1e6,1e6))的正方形,
以及(mathit n) 个水平的线段,(mathit m) 个垂直的线段,问画出所有的线段后,正方形被分割成的块数。
Ps:这(n+m) 个线段有共同的特点,就是每个线段与正方形的至少一条边相交,并且没有线段共线。
思路:
分析应该可以发现,所有线段(包括最初正方形的4个边)的交点总个数$sum $ ,减去所有线段个数+1就是正方形的块数。
然后问题就转化为求所有线段的交点个数,
通过分析发现,每个输入的线段与正方形的至少一条边相交,这个性质特别重要,
我们可以利用这个性质将其垂直的直线分为与上边界相交的和下边界相交的两类,
每一类我们可以将其不与边相交的那个点排序,组成一个单调序列,
然后用线段树进行区间修改,单点查询即可得到交点个数。
代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <bits/stdc++.h>
#define ALL(x) (x).begin(), (x).end()
#define sz(a) int(a.size())
#define rep(i,x,n) for(int i=x;i<n;i++)
#define repd(i,x,n) for(int i=x;i<=n;i++)
#define pii pair<int,int>
#define pll pair<long long ,long long>
#define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define MS0(X) memset((X), 0, sizeof((X)))
#define MSC0(X) memset((X), ' ', sizeof((X)))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define eps 1e-6
#define chu(x) if(DEBUG_Switch) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
#define du3(a,b,c) scanf("%d %d %d",&(a),&(b),&(c))
#define du2(a,b) scanf("%d %d",&(a),&(b))
#define du1(a) scanf("%d",&(a));
using namespace std;
typedef long long ll;
ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
ll lcm(ll a, ll b) {return a / gcd(a, b) * b;}
ll powmod(ll a, ll b, ll MOD) { if (a == 0ll) {return 0ll;} a %= MOD; ll ans = 1; while (b) {if (b & 1) {ans = ans * a % MOD;} a = a * a % MOD; b >>= 1;} return ans;}
ll poww(ll a, ll b) { if (a == 0ll) {return 0ll;} ll ans = 1; while (b) {if (b & 1) {ans = ans * a ;} a = a * a ; b >>= 1;} return ans;}
void Pv(const vector<int> &V) {int Len = sz(V); for (int i = 0; i < Len; ++i) {printf("%d", V[i] ); if (i != Len - 1) {printf(" ");} else {printf("
");}}}
void Pvl(const vector<ll> &V) {int Len = sz(V); for (int i = 0; i < Len; ++i) {printf("%lld", V[i] ); if (i != Len - 1) {printf(" ");} else {printf("
");}}}
inline long long readll() {long long tmp = 0, fh = 1; char c = getchar(); while (c < '0' || c > '9') {if (c == '-') fh = -1; c = getchar();} while (c >= '0' && c <= '9') tmp = tmp * 10 + c - 48, c = getchar(); return tmp * fh;}
inline int readint() {int tmp = 0, fh = 1; char c = getchar(); while (c < '0' || c > '9') {if (c == '-') fh = -1; c = getchar();} while (c >= '0' && c <= '9') tmp = tmp * 10 + c - 48, c = getchar(); return tmp * fh;}
void pvarr_int(int *arr, int n, int strat = 1) {if (strat == 0) {n--;} repd(i, strat, n) {printf("%d%c", arr[i], i == n ? '
' : ' ');}}
void pvarr_LL(ll *arr, int n, int strat = 1) {if (strat == 0) {n--;} repd(i, strat, n) {printf("%lld%c", arr[i], i == n ? '
' : ' ');}}
const int maxn = 1000010;
const int inf = 0x3f3f3f3f;
/*** TEMPLATE CODE * * STARTS HERE ***/
#define DEBUG_Switch 0
struct hor_line
{
int x1, x2, y;
} h[maxn];
struct ver_line
{
int y1, y2, x;
} v[maxn];
int n, m;
bool cmp(ver_line&aa, ver_line& bb)
{
if (aa.y1 != bb.y1)
{
return aa.y1 < bb.y1;
} else
{
return aa.y2 < bb.y2;
}
}
struct node
{
int l, r, val, laze;
} segment_tree[maxn << 2];
void build(int rt, int l, int r)
{
segment_tree[rt].l = l;
segment_tree[rt].r = r;
segment_tree[rt].val = segment_tree[rt].laze = 0;
if (l == r)
return ;
int mid = (l + r) >> 1;
build(rt << 1, l, mid);
build(rt << 1 | 1, mid + 1, r);
}
void push_down(int rt)
{
if (segment_tree[rt].laze)
{
int temp = segment_tree[rt].laze;
segment_tree[rt << 1].laze += temp;
segment_tree[rt << 1].val += temp;
segment_tree[rt << 1 | 1].laze += temp;
segment_tree[rt << 1 | 1].val += temp;
segment_tree[rt].laze = 0;
}
}
void push_up(int rt)
{
segment_tree[rt].val = segment_tree[rt << 1].val + segment_tree[rt << 1 | 1].val;
}
void update(int rt, int l, int r, int val)
{
if (segment_tree[rt].l >= l && segment_tree[rt].r <= r)
{
segment_tree[rt].laze += val;
segment_tree[rt].val += val;
return ;
}
push_down(rt);
int mid = segment_tree[rt].l + segment_tree[rt].r >> 1;
if (l <= mid)
update(rt << 1, l, r, val);
if (r > mid)
update(rt << 1 | 1, l, r, val);
push_up(rt);
}
int ask(int rt, int pos)
{
if (segment_tree[rt].l == pos && segment_tree[rt].r == pos)
{
return segment_tree[rt].val;
}
push_down(rt);
int mid = segment_tree[rt].l + segment_tree[rt].r >> 1;
if (pos <= mid)
return ask(rt << 1, pos);
else
return ask(rt << 1 | 1, pos);
}
bool cmp2(hor_line&aa, hor_line& bb)
{
return aa.y < bb.y;
}
int main()
{
#if DEBUG_Switch
freopen("C:\code\input.txt", "r", stdin);
#endif
//freopen("C:\code\output.txt","w",stdout);
n = readint();
m = readint();
repd(i, 1, n)
{
h[i].y = readint();
h[i].x1 = readint();
h[i].x2 = readint();
}
repd(i, 1, m)
{
v[i].x = readint();
v[i].y1 = readint();
v[i].y2 = readint();
}
h[++n] = hor_line{0, 1000000, 0};
h[++n] = hor_line{0, 1000000, 1000000};
v[++m] = ver_line{0, 1000000, 1000000};
v[++m] = ver_line{0, 1000000, 0};
sort(v + 1, v + 1 + m, cmp);
sort(h + 1, h + 1 + n, cmp2);
ll ans = 0ll;
build(1, 0, 1000000);
int l = 1;
int r = 0;
repd(i, 1, m)
{
while (r + 1 <= n && h[r + 1].y <= v[i].y2)
{
r++;
update(1, h[r].x1, h[r].x2, 1);
}
while (l <= n && h[l].y < v[i].y1)
{
update(1, h[l].x1, h[l].x2, -1);
l++;
}
ans += ask(1, v[i].x);
}
printf("%lld
" , max(1ll, ans - 3-(n-2)-(m-2) ));
return 0;
}