zoukankan      html  css  js  c++  java
  • HDU 1828 Picture

    HDU_1828

        以前只用离散化的思想写过这个题,现在又结合上线段树重新写了一遍。如果希望只沿一个方向扫描一遍就求出周长的话,那么相当于需要用两种方式分别求水平和竖直部分的周长。比如我们沿x方向扫描,那么竖直方向上的边长就需要通过矩形覆盖扫描线的总长度的变化值来计算,而水平方向上的边长就需要用点数乘以区间跨度去计算。

        其实感觉也可以在两个方法中任选一个,分别沿x、y方向各扫描一遍,也可以求出最后的周长。

        此外,如果我们沿x方向扫描,并按矩形覆盖的扫描线的总长度的变化值去计算竖直部分的边长的话,那么最初在对线段排序时,同一x值的线段一定要是矩形右边的边在前,是矩形左边的边在后。也就是说同一x位置上,要先进行添加边的操作,再进行删除边的操作,这是因为如果两条竖直边重合或有公共部分的话,我们如果先删再添就会多计算一部分长度。

    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    #define MAXD 10010
    int N, M, ty[4 * MAXD], num[4 * MAXD], lc[4 * MAXD], rc[4 * MAXD], len[4 * MAXD], cnt[4 * MAXD];
    struct Seg
    {
    int x, y1, y2, col;
    }seg[4 * MAXD];
    int cmps(const void *_p, const void *_q)
    {
    Seg *p = (Seg *)_p, *q = (Seg *)_q;
    if(p->x == q->x)
    return p->col > q->col ? -1 : 1;
    return p->x < q->x ? -1 : 1;
    }
    int cmpy(const void *_p, const void *_q)
    {
    int *p = (int *)_p, *q = (int *)_q;
    return *p < *q ? -1 : 1;
    }
    void build(int cur, int x, int y)
    {
    int mid = (x + y) >> 1, ls = cur << 1, rs = (cur << 1) | 1;
    len[cur] = lc[cur] = rc[cur] = num[cur] = cnt[cur] = 0;
    if(x == y)
    return ;
    build(ls, x, mid);
    build(rs, mid + 1, y);
    }
    void update(int cur, int x, int y)
    {
    int ls = cur << 1, rs = (cur << 1) | 1;
    if(cnt[cur])
    {
    len[cur] = ty[y + 1] - ty[x];
    lc[cur] = rc[cur] = 1;
    num[cur] = 2;
    }
    else if(x == y)
    len[cur] = lc[cur] = rc[cur] = num[cur] = 0;
    else
    {
    len[cur] = len[ls] + len[rs];
    lc[cur] = lc[ls], rc[cur] = rc[rs];
    num[cur] = num[ls] + num[rs];
    if(rc[ls] && lc[rs])
    num[cur] -= 2;
    }
    }
    void init()
    {
    int i, j, k, x1, y1, x2, y2;
    for(i = 0; i < N; i ++)
    {
    scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
    j = i << 1, k = (i << 1) | 1;
    seg[j].x = x1, seg[k].x = x2;
    seg[j].y1 = seg[k].y1 = y1, seg[j].y2 = seg[k].y2 = y2;
    seg[j].col = 1, seg[k].col = -1;
    ty[j] = y1, ty[k] = y2;
    }
    N <<= 1;
    qsort(seg, N, sizeof(seg[0]), cmps);
    qsort(ty, N, sizeof(ty[0]), cmpy);
    M = -1;
    for(i = 0; i < N; i ++)
    if(i == 0 || ty[i] != ty[i - 1])
    ty[++ M] = ty[i];
    build(1, 0, M - 1);
    }
    void refresh(int cur, int x, int y, int s, int t, int c)
    {
    int mid = (x + y) >> 1, ls = cur << 1, rs = (cur << 1) | 1;
    if(x >= s && y <= t)
    {
    cnt[cur] += c;
    update(cur, x, y);
    return ;
    }
    if(mid >= s)
    refresh(ls, x, mid, s, t, c);
    if(mid + 1 <= t)
    refresh(rs, mid + 1, y, s, t, c);
    update(cur, x, y);
    }
    int BS(int y)
    {
    int mid, min = 0, max = M + 1;
    for(;;)
    {
    mid = (min + max) >> 1;
    if(mid == min)
    break;
    if(ty[mid] <= y)
    min = mid;
    else
    max = mid;
    }
    return mid;
    }
    void solve()
    {
    int i, j, k, ans, prelen;
    ans = prelen = 0;
    seg[N].x = seg[N - 1].x;
    for(i = 0; i < N; i ++)
    {
    j = BS(seg[i].y1), k = BS(seg[i].y2);
    refresh(1, 0, M - 1, j, k - 1, seg[i].col);
    ans += num[1] * (seg[i + 1].x - seg[i].x);
    ans += abs(len[1] - prelen);
    prelen = len[1];
    }
    printf("%d\n", ans);
    }
    int main()
    {
    while(scanf("%d", &N) == 1)
    {
    init();
    solve();
    }
    return 0;
    }

     

  • 相关阅读:
    我的博客即将入驻“云栖社区”,诚邀技术同仁一同入驻。
    VGA显示器如何连接HDMI接口主机
    h5ai搭建自己的文件分享程序
    阿里钉钉智能硬件产品上线企业0元购买
    chevereto搭建自己的图床站点
    简单配置webpack自动刷新浏览器
    简易nodejs爬虫抓取博客园指定用户的文章及浏览量
    使用es6的set和map实现数组去重复
    promise实例小球运动
    ImportError: Couldn't import Django.
  • 原文地址:https://www.cnblogs.com/staginner/p/2438320.html
Copyright © 2011-2022 走看看