首页 > 其他分享 >[lnsyoj283/luoguP1856/IOI1998]矩形周长Picture

[lnsyoj283/luoguP1856/IOI1998]矩形周长Picture

时间:2024-06-08 18:33:51浏览次数:7  
标签:Picture luoguP1856 val lnsyoj283 int tree len hai2v 矩形

题意

原题链接
求几个矩形的周长并

sol

遇到几何图形的**并,都可以使用扫描线思想来解决
观察易得,与x轴平行的边和与y轴平行的边相互独立,因此可以扫描两次,分别计算并累加
以与x轴平行的边为例:
假设有一条平行于x轴的直线从下到上扫描,每当遇到一条边时,若这条边是某个矩形的下边,则在直线上覆盖这条边,否则就在直线上清除掉对应下边的覆盖标记。我们设这是第\(i\)条边,在直线上有\(len_i\)单位长度被覆盖,则第\(i\)条边的贡献为\(|len_i - len_{i-1}|\),特别地,\(len_0 = 0\)

证明

当遇到一条边时,可能会有两种情况:

  1. 这条边是下边,则这条边中处于矩形并的部分不会计算贡献,而不位于矩形并中的部分的贡献为\(len_i - len_{i-1}\)
  2. 这条边是上边,则这条边处于除该矩形的所有矩形的并的部分不会计算贡献,而不位于该并的部分的贡献为\(len_{i-1} - len_i\)

综上,该边的贡献为\(|len_i - len_{i-1}|\)


因此,我们只需要处理以下三个操作:

  1. 在直线上的一个区间覆盖标记
  2. 在直线上删除一个区间的覆盖标记
  3. 查询被覆盖的单位长度

对于本题来说,由于数据较弱,因此这三个操作即便是\(O(n)\)的暴力也不会TLE,但对本题来说,仍可以使用线段树来优化到\(O(n\log n)\)
我们可以在线段树上记录两个变量:\(cnt\)表示该区间被覆盖的次数,\(val\)表示该区间被覆盖的单位长度。在UPDATE时,我们可以将边对应的值直接加到\(cnt\)中,若是矩形下边,该值就为\(1\),上边则为\(0\)。然后,若这个区间被整体覆盖过,即\(cnt \le 1\),则\(val\)就为区间长度,否则\(val\)为两个儿子的\(val\)之和
值得注意的是,由于单个点对于周长的贡献毫无意义,因此每个节点\(\{l, r\}\)都应维护区间\([l, r+1]\)的贡献。为了达成这个目的,在UPDATE时要将右端点\(-1\),在PUSHUP时再将其\(+1\)
同时,由于部分题目坐标为浮点数、坐标范围过大等原因,需要进行离散化(虽然本题不用)
最后,在查询时,只需要查询根节点的\(val\)就可以了

代码

#include <iostream>
#include <algorithm>
#include <cstring>
#include <unordered_map>

using namespace std;

const int N = 10005;

struct Line{
    int pos, a, b, tag;
    bool operator< (const Line W) const{
        if (pos != W.pos) return pos < W.pos;
        return tag > W.tag;
    }
}row[N], col[N]; //扫描线

struct Node{
    int val, cnt;
}treer[N * 4], treec[N * 4]; //线段树

int n;
int hai2vr[N], hai2vc[N]; //将下标转为值

int hav2i(int *hai2v, int n, int x){ //将值转换为下标
    return lower_bound(hai2v, hai2v + n, x) - hai2v;
}

int discr(Line *lines, int *hai2v){ //离散化
    sort(hai2v, hai2v + n);
    int i, j;
    for (i = 1, j = 1; i < n; i ++ )
        if (hai2v[i] != hai2v[i - 1]) hai2v[j ++ ] = hai2v[i];
    for (i = 0; i < n; i ++ ){
        Line &line = lines[i];
        line.a = hav2i(hai2v, j, line.a);
        line.b = hav2i(hai2v, j, line.b);
    }
    return j;
}

void pushup(Node *tree, int *hai2v, int u, int l, int r){
    if (tree[u].cnt) tree[u].val = hai2v[r + 1] - hai2v[l];
    else tree[u].val = tree[u << 1].val + tree[u << 1 | 1].val;
}

void update(Node *tree, int *hai2v, int u, int l, int r, int L, int R, int val){
    if (L <= l && r <= R){
        tree[u].cnt += val;
        pushup(tree, hai2v, u, l, r);
        return ;
    }
    int mid = l + r >> 1;
    if (L <= mid) update(tree, hai2v, u << 1, l, mid, L, R, val);
    if (R > mid) update(tree, hai2v, u << 1 | 1, mid + 1, r, L, R, val);
    pushup(tree, hai2v, u, l, r);
}

int solve(Line *lines, Node *tree, int *hai2v){ //解题主函数
    int nn = discr(lines, hai2v);
    sort(lines, lines + n);
    int ans = 0;
    for (int i = 0, last = 0; i < n; i ++ ){
        Line line = lines[i];
        update(tree, hai2v, 1, 0, nn - 1, line.a, line.b - 1, line.tag);
        ans += abs(tree[1].val - last);
        last = tree[1].val;
    }

    return ans;
}

int main(){
    scanf("%d", &n);
    for (int i = 0; i < n; i ++ ){
        int x1, y1, x2, y2;
        scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
        row[i * 2] = {y1, x1, x2, 1};
        row[i * 2 + 1] = {y2, x1, x2, -1};
        col[i * 2] = {x1, y1, y2, 1};
        col[i * 2 + 1] = {x2, y1, y2, -1};
        hai2vr[i * 2] = x1, hai2vr[i * 2 + 1] = x2;
        hai2vc[i * 2] = y1, hai2vc[i * 2 + 1] = y2;
    }
    n *= 2;
    printf("%d\n", solve(row, treer, hai2vr) + solve(col, treec, hai2vc));
}

蒟蒻犯的若至错误

  • 线段树区间的叶子节点处理成了单点导致无效贡献
  • UPDATE操作中,被完全覆盖没有return

标签:Picture,luoguP1856,val,lnsyoj283,int,tree,len,hai2v,矩形
From: https://www.cnblogs.com/XiaoJuRuoUP/p/18238689/lnsyoj283_luoguP1856

相关文章

  • PictureCleaner:一款实用的本地图片处理工具
    PictureCleaner:一款实用的本地图片处理工具简介:对于日常办公和学习生活中图片处理的需求,今天推荐一款名为PictureCleaner的实用软件。这款软件专为Windows系统打造,具备多种图片处理功能,且完全免费、无广告,无需安装即可使用。主要功能:图片矫正:对于拍照时出现的倾斜或变形,Pictu......
  • Picturesocial | 只要 5 分钟,发现容器编排的秘密武器!
    在上一篇文章《Picturesocial|开发实践:如何在15分钟内将应用容器化》,我们讨论了容器以及容器化应用程序所需的步骤。在不考虑将container部署到哪里的情况下创建container,就像把家放在漂浮在海中的货运集装箱里一样,听起来既浪漫又可怕。如果想过上安全而惬意的生活,肯定需要......
  • CISCN_2018Picture_misc_wp
    CISCN_2018Picture_misc_wp思路第一关文件分离拿到一张图片,看到jpeg格式文件结尾之后依旧还有数据,猜想可能是隐藏了某些文件直接拿到binwalk中分析一下可以看到里面又一个zlib压缩包直接binwalk-e--run-as=root'[CISCN2018]Picture.jpg'直接得到压缩包的结果第......
  • Picturesocial | 开发实践:如何在15分钟内将应用容器化
    在常见的软件架构体系中,容器无疑是一个技术热点。有些开发者在工作中熟练使用容器技术,有些可能刚刚开始容器之旅。面对容器使用经验不同的各类开发者,我们希望通过这个系列文章,由浅入深地介绍如何使用容器技术来构建,运维我们的软件应用程序。贯穿整个系列,我们将持续构建一个名为......
  • CF1850E Cardboard for Pictures
    越界问题处理这题本身很简单,二分答案就行。但是数据很大,提前开了ULL还是越界。shortcheck(llx,vector<ll>a){ llsum=0; for(inti=1;i<=n;i++) { sum=sum+(a[i]+x)*(a[i]+x);//这里的sum是很可能越界的 } if(sum==c)return1; elseif(s......
  • Vue3 + [email protected] + UploadPictureCard
    <template><a-uploadname="file"v-model:file-list="showFileList"list-type="picture-card":multiple="multiple":max-count="maxCount":before-up......
  • 【论文阅读笔记】【OCR-文本识别】 CLIPTER: Looking at the Bigger Picture in Scene
    CLIPTERICCV2023读论文思考的问题论文试图解决什么问题?现有的文本识别方法只关注于局部截取的文本区域,识别模型并没有利用全图的上下文信息,导致其可能对有挑战性的文本的识别效果较差能否以某种方式使识别器利用上globalfeature的信息?文章提出了什么样的解决......
  • SP15637 GNYR04H - Mr Youngs Picture Permutations(线性 dp)
    题目求方案数,考虑dp——状态设计和边界——题目告诉了一个很显然的性质:每一排从左至右保证高度单调递减每一列从后往前保证高度单调递减那么可以发现,对于每一行,每一列,一定是按高度顺序插入,并且是连续插入,因为如果不连续,就无法保证单调递减的性质同时,它给出了另一个性......
  • VBA Picture Copy&Paste
    setmyshapes=.worksheets(1).shapes(“1”)myshapes.CopyPictureAppearance:=xlScreen,Format:=xlPictureThisWorkbook.Worksheets("Sheet3").PasteDestination:=ThisWorkbook.Worksheets("Sheet3").Cells(s,c)``SubpictureCV()Application.Scr......
  • MPEG(Moving Picture Experts Group)协议发展史
    MPEG(MovingPictureExpertsGroup)是一个国际标准化组织,致力于制定数字多媒体编码标准。MPEG协议的发展史可以追溯到20世纪80年代初。以下是MPEG协议的主要发展历程:MPEG-1:发布时间:1993年MPEG-1是MPEG协议的第一个版本,主要用于压缩视频和音频。它最著名的应用之一是VideoCD(VCD),这是......