当前位置: 首页 > news >正文

刷题记录:牛客NC24309Overplanting (Silver)

传送门:牛客

题目描述:

Farmer John has purchased a new machine that is capable of planting grass within any rectangular region of 
his farm that is "axially aligned" (i.e., with vertical and horizontal sides). Unfortunately, the machine 
malfunctions one day and plants grass in not one, but N (1 <= N <= 1000) different rectangular regions, some 
of which may even overlap. 
Given the rectangular regions planted with grass, please help FJ compute the total area in his farm that is 
now covered with grass.
输入:
2
0 5 4 1
2 4 6 2
输出:
20

一道扫描线的题目.但是因为数据范围比较小,所以可以使用二维差分来做

但是我既然是在线段树的题单中碰到了这道题,当然就直接用线段树做啦.毕竟用线段树来实现扫描线本身就是对二维差分做法的优化

对于扫描线算法,网上有大量博客对此进行讲解,此处就不在赘述了

为各位在提供一个有关这道题的另一种题面(不要换了题面就不会做了):

有一个数列,初始值均为0,他进行N次操作,每次将数列[ai,bi)这个区间中所有比Hi小的数改为Hi,他想知道N次操作后数列中所有元素的和。

看了这个题面有没有感觉扫描线的一些神奇之处??感觉有点积分的思想在那里了,反正我刚开始看到这道题(当我学完扫描线之后),我当时仍然是不知道怎么做的,根本就没有往扫描线那里想,还在想该怎么维护这道题.

优化&巧妙的想法:对于这种只需要区间[1,n]的维护值来说,我们建立线段树的时候可以不使用pushdown(因为我们根本不需要关注子节点是怎么样的),在子节点pushup的时候将父节点对子节点的lazy加上即可.
注意,此方法在我看来并不具有很强的意义,虽然省去了对子节点的维护,码量减少了,但是因为这种方式大大的修改了模板,会导致出现一写奇奇怪怪的错误甚至思维上的混乱,在比赛时并不建议这么做,但是在平时可以尝试一下,这样改变常规的做法可以大大增强自己对线段树的理解

下面是具体的代码部分(标准版维护版):

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define root 1,n,1
#define ls rt<<1
#define rs rt<<1|1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
inline ll read() {ll x=0,w=1;char ch=getchar();for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') w=-1;for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';return x*w;
}
#define int long long
#define maxn 1000000
const double eps=1e-8;
#define	int_INF 0x3f3f3f3f
#define ll_INF 0x3f3f3f3f3f3f3f3f
struct Segment_tree{int l,r,cov,lazy;
}tree[maxn*8];
struct Line{int l,r,y,cate;
}line[maxn];
bool cmp(Line A,Line B) {if(A.y==B.y) return A.l<B.l;else return A.y<B.y;
}
int n;vector<int>v;
int Getid(int x) {return lower_bound(v.begin(),v.end(),x)-v.begin()+1;
}
void build(int l,int r,int rt) {tree[rt].l=l;tree[rt].r=r;if(l==r) return ;int mid=(l+r)>>1;build(lson);build(rson);
}
void pushup(int rt) {tree[rt].cov=min(tree[ls].cov,tree[rs].cov);
}
void change(int rt,int val) {tree[rt].cov+=val;tree[rt].lazy+=val;
}
void pushdown(int rt) {change(ls,tree[rt].lazy);change(rs,tree[rt].lazy);tree[rt].lazy=0;
}
void update(int l,int r,int val,int rt) {if(tree[rt].l==l&&tree[rt].r+1==r) {change(rt,val);return ;}if(tree[rt].lazy) pushdown(rt);int mid=(tree[rt].l+tree[rt].r)>>1;if(r<=mid+1) update(l,r,val,ls);else if(l>=mid+1) update(l,r,val,rs);else update(l,mid+1,val,ls),update(mid+1,r,val,rs);pushup(rt);
}
int query(int l,int r,int rt) {if(tree[rt].l==l&&tree[rt].r+1==r) {if(tree[rt].cov) return v[r-1]-v[l-1];else if(tree[rt].l==tree[rt].r) return 0; }if(tree[rt].lazy) pushdown(rt);int mid=(tree[rt].l+tree[rt].r)>>1;if(r<=mid+1) return query(l,r,ls);else if(l>=mid+1) return query(l,r,rs);else return query(l,mid+1,ls)+query(mid+1,r,rs);
}
signed main() {n=read();int cnt=0;for(int i=1;i<=n;i++) {int x1=read(),y1=read(),x2=read(),y2=read();line[++cnt].l=x1;line[cnt].r=x2;line[cnt].y=min(y1,y2);line[cnt].cate=1;line[++cnt].l=x1;line[cnt].r=x2;line[cnt].y=max(y1,y2);line[cnt].cate=-1;v.push_back(x1);v.push_back(x2);}sort(v.begin(),v.end());v.erase(unique(v.begin(),v.end()),v.end());int Size=v.size();build(1,Size,1);sort(line+1,line+2*n+1,cmp);int ans=0;int pre=0;for(int i=1;i<=2*n-1;i++) {int x=Getid(line[i].l),x2=Getid(line[i].r);update(x,x2,line[i].cate,1);ans+=query(1,Size,1)*(line[i+1].y-line[i].y);}cout<<ans<<endl;return 0;
}

下面是具体的代码部分(不维护pushdownpushdownpushdown版):

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define root 1,n,1
#define ls rt<<1
#define rs rt<<1|1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
inline ll read() {ll x=0,w=1;char ch=getchar();for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') w=-1;for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';return x*w;
}
#define int long long
#define maxn 1000000
const double eps=1e-8;
#define	int_INF 0x3f3f3f3f
#define ll_INF 0x3f3f3f3f3f3f3f3f
struct Segment_tree{int l,r,cov,len;
}tree[maxn*8];
struct Line{int l,r,y,cate;
}line[maxn];
bool cmp(Line A,Line B) {if(A.y==B.y) return A.l<B.l;else return A.y<B.y;
}
int n;
void build(int l,int r,int rt) {tree[rt].l=l;tree[rt].r=r;tree[rt].cov=0;tree[rt].len=0;if(l==r) return ;int mid=(l+r)>>1;build(lson);build(rson);
}
vector<int>v;
void pushup(int rt) {if(tree[rt].cov) tree[rt].len=v[tree[rt].r]-v[tree[rt].l-1];else tree[rt].len=tree[ls].len+tree[rs].len;
}
void update(int l,int r,int rt,int val) {if(tree[rt].l==l&&tree[rt].r+1==r) {tree[rt].cov+=val;if(tree[rt].cov!=0) tree[rt].len=v[r-1]-v[l-1];else pushup(rt);return ;}int mid=(tree[rt].l+tree[rt].r)>>1;if(r<=mid+1) update(l,r,ls,val);else if(l>=mid+1) update(l,r,rs,val);else update(l,mid+1,ls,val),update(mid+1,r,rs,val);pushup(rt);
}
int Getid(int x) {return lower_bound(v.begin(),v.end(),x)-v.begin()+1;
}
signed main() {n=read();int cnt=0;for(int i=1;i<=n;i++) {int x1=read(),y1=read(),x2=read(),y2=read();line[++cnt].l=x1;line[cnt].r=x2;line[cnt].y=min(y1,y2);line[cnt].cate=1;line[++cnt].l=x1;line[cnt].r=x2;line[cnt].y=max(y1,y2);line[cnt].cate=-1;v.push_back(x1);v.push_back(x2);}sort(v.begin(),v.end());v.erase(unique(v.begin(),v.end()),v.end());int Size=v.size();build(1,Size,1);sort(line+1,line+2*n+1,cmp);int ans=0;int pre=0;for(int i=1;i<=2*n-1;i++) {int x=Getid(line[i].l),x2=Getid(line[i].r);update(x,x2,1,line[i].cate);ans+=tree[1].len*(line[i+1].y-line[i].y);}cout<<ans<<endl;return 0;
}
http://www.lryc.cn/news/18017.html

相关文章:

  • Spring Boot中使用Sa-Token实现轻量级登录与鉴权
  • 《分布式技术原理与算法解析》学习笔记Day20
  • 【2023-2-23】FastDeploy 安装教程
  • rollup.js 一个简单实用的打包工具
  • 数据结构与算法之最小爬楼梯费用动态规划
  • 阿里云ACA认证如何获取?
  • 【Python入门第十六天】Python If ... Else
  • 两数之和的解法
  • 领导催我优化SQL语句,我求助了ChatGPT。这是ChatGPT给出的建议,你们觉得靠谱吗
  • ArcGIS手动分割矢量面要素从而划分为多个面部分的方式:Cut Polygons Tool
  • 【LeetCode】剑指 Offer 13. 机器人的运动范围 p92 -- Java Version
  • [oeasy]python0091_仙童公司_八叛逆_intel_8080_altair8800_牛郎星
  • crontab 执行脚本报错,手动执行脚本正常的解决方法
  • 扎心话题 | 设计院背后的潜规则你知道吗?
  • 【JavaEE初阶】第二节.多线程( 进阶篇 ) 锁的优化、JUC的常用类、线程安全的集合类
  • 大数据核心技术是什么
  • 「TCG 规范解读」初识 TPM 2.0 库续一
  • task与function
  • Android 基础知识4-3.1 TextView(文本框)详解
  • 点击化学 PEG 试剂1858242-47-3,Propargyl丙炔基-PEG1-乙酸活性酯
  • 正则表达式是如何运作的?
  • JVM参数GC线程数ParallelGCThreads设置
  • java 线程的那些事
  • 如何利用 Python 进行客户分群分析(附源码)
  • D1s RDC2022纪念版开发板开箱评测及点屏教程
  • 了解一下TCP/IP协议族
  • 【第十九部分】存储过程与存储函数
  • 字节序
  • PDF文件怎么转图片格式?转换有技巧
  • 筑基七层 —— 数据在内存中的存储?拿来吧你