扫描线总结【线段树特殊性质,没有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开始相等的最长连续长度 分析:树状数组可以维护一个区间内公共长度(连续)的情况,查询时用二分查找最远的端点即 ...
随机推荐
- Vue+element ui 笔记
1)可以直接拿过来就用的样式 https://www.cnblogs.com/xiao987334176/p/14188413.html 2)对Table里面的每一项全部设定为选中 mounted() ...
- [NOIP1999 提高组] 旅行家的预算
洛咕 题意:一个旅行家想驾驶汽车以最少的费用从一个城市到另一个城市(假设出发时油箱是空的).给定两个城市之间的距离 \(D_1\).汽车油箱的容量 \(C\)(以升为单位).每升汽油能行驶的距离 \( ...
- el-table更新数据页面闪烁问题
情况是这样,渲染了一个table,高度是固定的.所以会有滚动.其中的某一列的数据只显示了部分内容,鼠标浮上加载全部,用el-popover浮框显示. 但每次改变tableKey会触发整个table的重 ...
- 学习Anaconda,jupyter notebook
20200210,理解了jupyter在anaconda中的意义,vs code觉得对我这个初学者来讲,更容易使用,pycharm虽然破解安装了,但是感觉不太好用,随后再说 20200211, jup ...
- STM32中HAL库和标准库的区别
转载自:https://www.lmonkey.com/t/RwykY8bBX STM32标准库与HAL库比较 ST为开发者提供了非常方便的开发库.到目前为止,有标准外设库(STD库).HAL库.LL ...
- continue练习
using System; namespace continue_的练习 { class Program { static void Main(string[] args) { int sum = 0 ...
- java字符串和图片相互转换
package com.thinkgem.jeesite.modules.api.wechat; import sun.misc.BASE64Decoder; import sun.misc.BASE ...
- Web Dynpro for ABAP(15):Print
3.20 Print WDA调用浏览器打印界面 1.创建Print按钮,绑定事件PRINT; 2.实现ONACTIONPRINT事件: method ONACTIONPRINT. DATA:l_api ...
- TypeScript - 安装,类型
// 要使用typescript需要全局安装 通过tsc -v 来验证是否安装成功 npm i -g typescript// ts 文件中完全可以写js语法, 完全兼容js // ts 本身在运行时 ...
- nacos2.1 新增配置发布失败。请检查参数是否正确
使用官方的docker部署方式,部署了一个单节点nacos server,部署完了后发布配置信息,报错"新增配置发布失败.请检查参数是否正确" 解决方法: 在nacos mysql ...