POJ1177 Picture(待补)

题目链接:Picture

大致题意

现在有平面直角坐标系xoy, 有n个平行于x轴y轴的矩形, 给出这些矩形的左下角和右上角的坐标, 让你求出这些矩形组成的图形的周长是多少

解题思路

本文参考博客

还没学会… 高估自己了QAQ 大家看大佬这篇博客吧

AC代码

#include <iostream>
#include <vector>
#include <cstdio>
#include <algorithm>
#define rep(i, n) for (int i = 1; i <= (n); ++i)
using namespace std;
typedef long long ll;
const int N = 1E4 + 10;

vector<int> v;
int find(int x) { return lower_bound(v.begin(), v.end(), x) - v.begin(); }

struct LINE {
    int x, y1, y2; int c;
    bool operator< (const LINE& t) const { return x < t.x; }
}; vector<LINE> line;


struct node {
    int l, r;
    int cou; bool lf, rf; int num;
    int len;
}t[N << 3];

int getlen(int l, int r) { return v[r + 1] - v[l]; }
void pushup(int x) {
    if (t[x].cou) {
        t[x].len = getlen(t[x].l, t[x].r);
        t[x].lf = t[x].rf = 1;
        t[x].num = 1;
    }
    else if (t[x].l != t[x].r) {
        t[x].len = t[x << 1].len + t[x << 1 | 1].len;
        t[x].lf = t[x << 1].lf, t[x].rf = t[x << 1 | 1].rf;
        t[x].num = t[x << 1].num + t[x << 1 | 1].num - (t[x << 1].rf & t[x << 1 | 1].lf);
    }
    else {
        t[x].len = 0;
        t[x].lf = t[x].rf = 0;
        t[x].num = 0;
    }
}

void build(int l, int r, int x = 1) {
    t[x] = { l, r, 0, 0, 0, 0, 0 };
    if (l == r) return;
    int mid = l + r >> 1;
    build(l, mid, x << 1), build(mid + 1, r, x << 1 | 1);
}

void modify(int l, int r, int c, int x = 1) {
    if (l <= t[x].l && r >= t[x].r) {
        t[x].cou += c;
        pushup(x);
        return;
    }
    int mid = t[x].l + t[x].r >> 1;
    if (l <= mid) modify(l, r, c, x << 1);
    if (r > mid) modify(l, r, c, x << 1 | 1);
    pushup(x);
}
int main()
{
    int n;
    while (~scanf("%d", &n)) {
        v.clear(); line.clear(); v.push_back(-0x3f3f3f3f); //别忘了初始化
        rep(i, n) {
            int x1, y1, x2, y2; scanf("%d %d %d %d", &x1, &y1, &x2, &y2);
            line.push_back({ x1, y1, y2, 1 });
            line.push_back({ x2, y1, y2, -1 });
            v.push_back(y1), v.push_back(y2);
        }
        sort(v.begin(), v.end()); v.erase(unique(v.begin(), v.end()), v.end());
        build(1, v.size() - 2);
        
        sort(line.begin(), line.end());
        
        int res = 0, lastlen = 0, lastx = 0;
        for (int i = 0; i < line.size(); ++i){
            LINE& op = line[i];
            res += abs(t[1].len - lastlen);
            res += (op.x - lastx) * 2 * t[1].num;
            lastlen = t[1].len, lastx = op.x;
            modify(find(op.y1), find(op.y2) - 1, op.c);
        }
        res += lastlen, res += lastx * 2 * t[1].num;
        printf("%d\n", res);
    }
    return 0;
}
kuangbin线段树专题点这里!!!

END

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

逍遥Fau

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值