WuliWuliiii
凤兮凤兮归故乡 遨游四海求其凰

题目链接

  我们可以讲块坐标改成点坐标,然后再进行离散化,然后就是一个经典的扫面线问题了,如果b大于1的时候,横着扫完再竖着扫一遍就可以了。

  这时候扫描线的pushup该怎么写呢?我们用ls记录当前线段树上的节点的左连续白色的长度,rs记录当前线段树上的节点的右连续白色的长度,tree记录当前线段树上的节点对应的长b宽1的长方形的个数。

  于是,pushup就变成了如下情况:

   tree[rt] = tree[lsn] + tree[rsn];

(1)如果rs[lsn] >= b && ls[rsn] >= b,此时tree[rt] += b - 1;因为两边的中间合并,并且两边都各自算过贡献了,(b-1)被多算了一遍,所以要加回去;

(2)如果只有rs[lsn] >= b,此时再加上个ls[rsn]即可;

(3)同理ls[rsn] >= b;

(4)剩下的,如果rs[lsn] + ls[rsn] >= b,tree[rt] += rs[lsn] + ls[rsn] - b + 1。

  于是,剩下就是简单的扫描线问题了。

  当然, 一定不要写错lsn和rsn,不然debug还是蛮累的。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <bitset>
#include <unordered_map>
#include <unordered_set>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
#define pii pair<int, int>
#define MP(a, b) make_pair(a, b)
using namespace std;
typedef unsigned long long ull;
typedef unsigned int uit;
typedef long long ll;
const int maxN = 2e5 + 7;
int C, V, N, a, b, lsan[maxN], _UP;
struct Matrice
{
    int lx, ly, rx, ry;
    void In() { scanf("%d%d%d%d", &lx, &ly, &rx, &ry); rx ++; ry ++; }
} t[maxN];
struct Line
{
    int l, r, y, op;
    Line(int a=0, int b=0, int c=0, int d=0):l(a), r(b), y(c), op(d) {}
    friend bool operator < (Line e1, Line e2)
    { return e1.y == e2.y ? e1.op > e2.op : e1.y < e2.y; }
} edge[maxN];
const int maxP = maxN << 2;
int ls[maxP], rs[maxP], tree[maxP];
ll ans = 0;
void build(int rt, int l, int r)
{
    ls[rt] = rs[rt] = lsan[r + 1] - lsan[l];
    if(ls[rt] >= b) tree[rt] = ls[rt] - b + 1;
    if(l == r) return;
    int mid = HalF;
    build(Lson);
    build(Rson);
}
void pushup(int rt, int l, int r)
{
    int mid = HalF;
    ls[rt] = ls[lsn];
    rs[rt] = rs[rsn];
    if(ls[lsn] == lsan[mid + 1] - lsan[l]) ls[rt] += ls[rsn];
    if(rs[rsn] == lsan[r + 1] - lsan[mid + 1]) rs[rt] += rs[lsn];
    tree[rt] = tree[lsn] + tree[rsn];
    if(ls[rsn] + rs[lsn] >= b)
    {
        if(ls[rsn] >= b && rs[lsn] >= b) tree[rt] += b - 1;
        else if(ls[rsn] >= b) tree[rt] += rs[lsn];
        else if(rs[lsn] >= b) tree[rt] += ls[rsn];
        else tree[rt] += ls[rsn] + rs[lsn] - b + 1;
    }
}
void update(int rt, int l, int r, int ql, int qr, int val)
{
    if(ql <= l && qr >= r)
    {
        if(val > 0)
        {
            ls[rt] = rs[rt] = lsan[r + 1] - lsan[l];
            if(ls[rt] >= b) tree[rt] = ls[rt] - b + 1;
        }
        else
        {
            ls[rt] = rs[rt] = 0;
            tree[rt] = 0;
        }
        return;
    }
    int mid = HalF;
    if(qr <= mid) update(QL, val);
    else if(ql > mid) update(QR, val);
    else { update(QL, val); update(QR, val); }
    pushup(myself);
}
void Solve()
{
    _UP = 0;
    int n = 0;
    for(int i = 1; i <= N; i ++)
    {
        lsan[++ _UP] = t[i].ly;
        lsan[++ _UP] = t[i].ry;
        edge[++ n] = Line(t[i].ly, t[i].ry, t[i].lx, -1);
        edge[++ n] = Line(t[i].ly, t[i].ry, t[i].rx, +1);
    }
    lsan[++ _UP] = 1; lsan[++ _UP] = V;
    sort(lsan + 1, lsan + _UP + 1);
    _UP = (int)(unique(lsan + 1, lsan + _UP + 1) - lsan - 1);
    sort(edge + 1, edge + n + 1);
    build(1, 1, _UP - 1);
    if(n) ans += 1LL * (edge[1].y - 1) * tree[1];
    else ans += 1LL * (C - 1) * tree[1];
    for(int i = 1, ql, qr; i <= n; i ++)
    {
        ql = (int)(lower_bound(lsan + 1, lsan + _UP + 1, edge[i].l) - lsan);
        qr = (int)(lower_bound(lsan + 1, lsan + _UP + 1, edge[i].r) - lsan - 1);
        update(1, 1, _UP - 1, ql, qr, edge[i].op);
        if(i < n) ans += 1LL * (edge[i + 1].y - edge[i].y) * tree[1];
        else ans += 1LL * (C - edge[i].y) * tree[1];
    }
}
int main()
{
    scanf("%d%d%d%d%d", &C, &V, &N, &a, &b); C ++; V ++;
    for(int i = 1; i <= N; i ++) t[i].In();
    _UP = 0;
    int n = 0;
    for(int i = 1; i <= N; i ++)
    {
        lsan[++ _UP] = t[i].lx;
        lsan[++ _UP] = t[i].rx;
        edge[++ n] = Line(t[i].lx, t[i].rx, t[i].ly, -1);
        edge[++ n] = Line(t[i].lx, t[i].rx, t[i].ry, +1);
    }
    lsan[++ _UP] = 1; lsan[++ _UP] = C;
    sort(lsan + 1, lsan + _UP + 1);
    _UP = (int)(unique(lsan + 1, lsan + _UP + 1) - lsan - 1);
    sort(edge + 1, edge + n + 1);
    build(1, 1, _UP - 1);
    if(n) ans += 1LL * (edge[1].y - 1) * tree[1];
    else ans += 1LL * (V - 1) * tree[1];
    for(int i = 1, ql, qr; i <= n; i ++)
    {
        ql = (int)(lower_bound(lsan + 1, lsan + _UP + 1, edge[i].l) - lsan);
        qr = (int)(lower_bound(lsan + 1, lsan + _UP + 1, edge[i].r) - lsan - 1);
        update(1, 1, _UP - 1, ql, qr, edge[i].op);
        if(i < n) ans += 1LL * (edge[i + 1].y - edge[i].y) * tree[1];
        else ans += 1LL * (V - edge[i].y) * tree[1];
    }
    if(b > 1)
    {
        Solve();
    }
    printf("%lld\n", ans);
    return 0;
}
/*
4 4 2 1 2
1 1 2 2
3 3 4 4
ans:8
*/

 

posted on 2021-03-09 11:09  唔哩Wulili  阅读(69)  评论(0编辑  收藏  举报