扫描线总结【线段树特殊性质,没有pushdown、query操作】
扫描线
题意
多个矩阵求交集,线段树的特殊操作,非常特殊的情况,一堆证明之后,就没有pushdown操作。
没有pushdown操作,也没有query操作,直接tr[1].len.
亚特兰蒂斯
由于点可能有小数,先l、离散化为整数,这里的线段树存的是一个区间:【L,R),左闭右开的区间。 换句话:线段树存的是第几个小区间,那么操作(l,r)的话,对线段树操作:l–r-1就够了,(存的不是点,是小区间,小区间比点的数量少1)
另外,也不需要query()函数,之间调用tr[1].len,返回线段长度
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<map>
#include<queue>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define mst(s,_s) memset(s, _s, sizeof(s))
const double PI = acos(-1.0);
const double eps = 1e-6;
const int INF = 0x3f3f3f3f;
const int N = 1e6+100;
int T,n,m;
struct seg1{
double x,y1,y2;
int k;
bool operator<(const seg1 & t)const{
return x<t.x;
}
}seg[N];
struct node{
int l,r,cnt;
double len;
}tr[N];
vector<double>ys;
double find(double y)
{
return lower_bound(ys.begin(),ys.end(),y) - ys.begin();
}
void build(int u,int l,int r)
{
if(l==r) tr[u]={l,r,0,0.0};
else{
tr[u]={l,r,0,0.0};
int mid=l+r>>1;
build(u<<1,l,mid),build(u<<1|1,mid+1,r);
}
}
void pushup(int u)
{
if(tr[u].cnt)
{
tr[u].len=(ys[tr[u].r+1]-ys[tr[u].l]);
}
else if(tr[u].l!=tr[u].r)
{
tr[u].len= tr[u<<1].len+tr[u<<1|1].len;
}
else tr[u].len=0;
}
void modify(int u,int l,int r,int k)
{
if(tr[u].l>=l && tr[u].r<=r)
{
tr[u].cnt+=k;
pushup(u);
}
else{
int mid=tr[u].l+tr[u].r>>1;
if(l<=mid) modify(u<<1,l,r,k);
if(r>mid) modify(u<<1|1,l,r,k);
pushup(u);
}
}
int main() {
int T=1;
while(cin>>n)
{
if(n==0) break;
ys.clear();
for(int i=0,j=0;i<n;i++)
{
double x1,y1,x2,y2;
cin>>x1>>y1>>x2>>y2;
ys.push_back(y1);
ys.push_back(y2);
seg[j++]={x1,y1,y2,1};
seg[j++]={x2,y1,y2,-1};
}
sort(seg,seg+n*2);
sort(ys.begin(),ys.end());
ys.erase(unique(ys.begin(),ys.end()),ys.end());
build(1,0,ys.size()-2);
double res=0.0;
for(int i=0;i<2*n;i++)
{
if(i>0) res+=(tr[1].len * (seg[i].x-seg[i-1].x));
modify(1,find(seg[i].y1),find(seg[i].y2) -1 ,seg[i].k);
}
printf("Test case #%d\n", T ++ );
printf("Total explored area: %.2lf\n\n", res);
}
return 0;
}
普通版本扫描线
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<map>
#include<queue>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define mst(s,_s) memset(s, _s, sizeof(s))
const double PI = acos(-1.0);
const double eps = 1e-6;
const int INF = 0x3f3f3f3f;
const int N = 1e6+100;
int T,n,m;
struct seg1{
int x,y1,y2;
int k;
bool operator<(const seg1 & t)const{
return x<t.x;
}
}seg[N];
struct node{
int l,r,cnt;
int len;
}tr[N];
void build(int u,int l,int r)
{
if(l==r) tr[u]={l,r,0,0};
else{
tr[u]={l,r,0,0};
int mid=l+r>>1;
build(u<<1,l,mid);
build(u<<1|1,mid+1,r);
}
}
void pushup(int u)
{
if(tr[u].cnt) tr[u].len = tr[u].r+1-tr[u].l;
else if(tr[u].l!=tr[u].r) tr[u].len = tr[u<<1].len+tr[u<<1|1].len;
else{
tr[u].len=0;
}
}
void motify(int u,int l,int r,int k)
{
if(l<=tr[u].l && tr[u].r<=r)
{
tr[u].cnt+=k;
pushup(u);
}
else{
int mid=tr[u].l+tr[u].r>>1;
if(l<=mid) motify(u<<1,l,r,k);
if(r>mid) motify(u<<1|1,l,r,k);
pushup(u);
}
}
int main() {
cin>>n;
int m = 0;
for(int i=0,j=0;i<n;i++)
{
int x1,x2,y1,y2;
cin>>x1>>y1>>x2>>y2;
seg[j++]={x1,y1,y2,1};
seg[j++]={x2,y1,y2,-1};
}
//sort(seg, seg + m);
sort(seg,seg+2*n);
build(1,0,10000);
ll res=0;
for(int i=0;i<2*n;i++)
{
if(i>0) res+=tr[1].len * (seg[i].x - seg[i-1].x);
motify(1,seg[i].y1,seg[i].y2-1,seg[i].k);
}
cout<<res<<endl;
return 0;
}
扫描线总结【线段树特殊性质,没有pushdown、query操作】的更多相关文章
- HDU - 1542 扫描线入门+线段树离散化
扫描线算法+线段树维护简介: 像这种求面积的并集的题目,就适合用扫描线算法解决,具体来说就是这样 类似这种给出点的矩形的对角的点的坐标,然后求出所有矩形面积的交集的问题,可以采用扫描线算法解决.图如下 ...
- Atlantis HDU - 1542 (扫描线,线段树)
扫描线的模板题,先把信息接收,然后排序,记录下上边和下边,然后用一条虚拟的线从下往上扫.如果我扫到的是下边,那么久用线段树在这个区间内加上1,表示这个区间现在是有的,等我扫描到上边的时候在加上-1,把 ...
- poj 2482 Stars in Your Window + 51Nod1208(扫描线+离散化+线段树)
Stars in Your Window Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 13196 Accepted: ...
- 【BZOJ 3958】 3958: [WF2011]Mummy Madness (二分+扫描线、线段树)
3958: [WF2011]Mummy Madness Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 96 Solved: 41 Descripti ...
- 洛谷 P4125 [WC2012]记忆中的水杉树【扫描线+set+线段树】
我没有找到能在bzojAC的代码--当然我也WA了--但是我在洛谷过了,那就假装过了吧 minmax线段树一开始写的只能用min更新min,max更新max,实际上是可以互相更新的-- 首先看第二问, ...
- codeforces 447E or 446C 线段树 + fib性质或二次剩余性质
CF446C题意: 给你一个数列\(a_i\),有两种操作:区间求和:\(\sum_{i=l}^{r}(a[i]+=fib[i-l+1])\).\(fib\)是斐波那契数列. 思路 (一) codef ...
- [Usaco2014 Open Gold ]Cow Optics (树状数组+扫描线/函数式线段树)
这道题一上手就知道怎么做了= = 直接求出原光路和从目标点出发的光路,求这些光路的交点就行了 然后用树状数组+扫描线或函数式线段树就能过了= = 大量的离散+模拟+二分什么的特别恶心,考试的时候是想到 ...
- bzoj4822: [Cqoi2017]老C的任务(扫描线+BIT/线段树)
裸题... 依旧是写了BIT和线段树两种(才不是写完线段树后才想起来可以写BIT呢 怎么卡常数都挺大...QAQ ccz和yy的写法好快哇%%% BIT: #include<iostream&g ...
- BZOJ 2588: Spoj 10628. Count on a tree-可持久化线段树+LCA(点权)(树上的操作) 无语(为什么我的LCA的板子不对)
2588: Spoj 10628. Count on a tree Time Limit: 12 Sec Memory Limit: 128 MBSubmit: 9280 Solved: 2421 ...
- 二分+树状数组/线段树(区间更新) HDOJ 4339 Query
题目传送门 题意:给两串字符串,操作1:替换其中一个字符串的某个位置的字符 操作2:查询从p开始相等的最长连续长度 分析:树状数组可以维护一个区间内公共长度(连续)的情况,查询时用二分查找最远的端点即 ...
随机推荐
- 一些开源软件的LOGO
整理一些开源软件的logo或者吉祥物,主要是一些以动物形象为主的logo. 1. GNU,不是一个软件,而是一个软件组织,包括很多知名的软件例如GCC编译器. GNU的LOGO是一只牛. GCC的lo ...
- (K8s学习笔记八)Pod的扩缩容
1.手动扩容机制 示例:对busybox-deployment手动扩缩容 apiVersion:apps/v1 kind: Deployment metadata: name: busybox-dep ...
- laravel Auth的使用
最新的文档是使用的 laravel/jetstream 扩展包,旧版本中的 php artisan make:auth 命令在新版本中已不能用,但是此博客没有使用文档提供的扩展包,而是使用的是lara ...
- c++基础: uint8_t uint16_t uint32_t uint64_t size_t ssize_t数据类型
https://blog.csdn.net/lzx_bupt/article/details/7066577 在nesc的代码中,你会看到很多你不认识的数据类型,比如uint8_t等.咋一看,好像是个 ...
- python学习●错误点●expected an indented block
报错:expected an indented block 翻译:缩进错误 因为python判断句无{},所以要缩进空格代表优先级.
- SAP 布局编辑器无法使用问题处理
因一些事情,公司将正式系统的数据拷贝到了开发机,后来在开发中用到了布局编辑器,发现打不开且会报错RFC callback call rejected by whitelist 这个是因为正式机和开发机 ...
- JS学习-异步JS
异步JS setTimeout() 我们希望传递给setTimeout()中运行的函数的任何参数,都必须作为列表末尾的附加参数传递给它. function sayHi(who) { alert('He ...
- Oracle dump文件的一些经验
dump文件对于DBA而言再平常不过了.不过因为dump文件是二进制文件,我们平时使用中不太关注.再导入dump文件时有很多细节和技巧是值得注意的. 1.查看dump文件的一些基本信息 strings ...
- pyhon_元组(tuple)
定义: 元组中可以存储不一样类型的数据,使用小括号存储数据,中间用逗号进行分割. 元组中的数据定义好后,无法进行修改,有保护数据的目的. 格式化字符串定义多个值的时候,本质上也是元组. 测试: inf ...
- vue验证码倒计时60s
vue3验证码倒计时60s //倒计时60s const timeNum = ref(60); const countDown = ref(); const isShowSend = ref(true ...