SRM13绵津见-终(扫描线+线段树/BIT)
题目大意:求对于每个i求有多少个合法的j以及j对于几个i是合法的,合法的定义:l[i]<=x[j]<=r[i],T[i]-y[i]<=t[j]<=T[i]+y[i]。
设a[i]=T[i]-y[i],b[i]=T[i]+y[i]。
可以把题目看成一个(x[i],t[i])的点在多少个左上角为(l[i],a[i])右下角为(r[i],b[i])的矩阵中。
那么就从上到下扫每一行,每一行从左到右扫,以横坐标为线段树或BIT下标。
对于询问每个点在多少个矩阵中,可以使用差分,扫到矩阵顶部时+1,矩阵底部时-1(询问完点后再-1或者矩阵底部下一行-1再询问点都可以),那么在扫中间的时候所有点都会+1,单点查询答案即可。
对于询问每个矩阵中有多少个点,扫描线加入点,将询问一个矩阵拆成两个询问,扫到矩阵顶部时候记录下答案,扫到矩阵底部时记录下答案(记录完答案再加入这一行的点或者加入下一行的点前统计下一行的答案都可以),两者相减即为这个矩阵的答案。
BIT的话区间修改还需要差分一下。
线段树:
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=,inf=1e9;
struct tjm{int sum,delta;}tree[maxn*];
struct poi{int fir,sec,trd,pos,ty;}q[maxn*];
int n,m,cnt,cnt2,N;
int x[maxn],t[maxn],T[maxn],y[maxn],lisan[maxn],l[maxn],r[maxn],a[maxn],b[maxn],ans[maxn];
void read(int &k)
{
int f=;k=;char c=getchar();
while(c<''||c>'')c=='-'&&(f=-),c=getchar();
while(c<=''&&c>='')k=k*+c-'',c=getchar();
k*=f;
}
bool cmp1(poi a,poi b){return a.fir==b.fir?a.ty>b.ty:a.fir<b.fir;}
bool cmp2(poi a,poi b){return a.fir==b.fir?(a.ty==b.ty?a.sec<b.sec:a.ty<b.ty):a.fir<b.fir;}
inline void pushup(int x){tree[x].sum=tree[x<<].sum+tree[x<<|].sum;}
inline void pushdown(int x)
{
if(!tree[x].delta)return;
tree[x<<].delta+=tree[x].delta;tree[x<<|].delta+=tree[x].delta;
tree[x<<].sum+=tree[x].delta;tree[x<<|].sum+=tree[x].delta;
tree[x].delta=;
}
void add(int x,int l,int r,int cl,int cr,int delta)
{
if(cl<=l&&r<=cr){tree[x].sum+=delta;tree[x].delta+=delta;return;}
pushdown(x);
int mid=(l+r)>>;
if(cl<=mid)add(x<<,l,mid,cl,cr,delta);
if(cr>mid)add(x<<|,mid+,r,cl,cr,delta);
pushup(x);
}
void add2(int x,int l,int r,int cx,int delta)
{
if(l==r){tree[x].sum+=delta;return;}
int mid=(l+r)>>;
if(cx<=mid)add2(x<<,l,mid,cx,delta);
else add2(x<<|,mid+,r,cx,delta);
pushup(x);
}
int query(int x,int l,int r,int cl,int cr)
{
if(cl<=l&&r<=cr)return tree[x].sum;
pushdown(x);
int mid=(l+r)>>,ans=;
if(cl<=mid)ans+=query(x<<,l,mid,cl,cr);
if(cr>mid)ans+=query(x<<|,mid+,r,cl,cr);
return ans;
}
int main()
{
read(n);read(m);
for(int i=;i<=n;i++)read(t[i]),read(x[i]),lisan[++cnt2]=t[i];
for(int i=;i<=m;i++)read(T[i]),read(l[i]),read(r[i]),read(y[i]);
for(int i=;i<=m;i++)a[i]=T[i]-y[i],b[i]=T[i]+y[i];
for(int i=;i<=m;i++)lisan[++cnt2]=a[i],lisan[++cnt2]=b[i];
N=cnt2;N=unique(lisan+,lisan++N)-lisan-;sort(lisan+,lisan++N);
for(int i=;i<=m;i++)
{
a[i]=lower_bound(lisan+,lisan++N,a[i])-lisan;
b[i]=lower_bound(lisan+,lisan++N,b[i])-lisan;
}
for(int i=;i<=n;i++)
t[i]=lower_bound(lisan+,lisan++N,t[i])-lisan;
for(int i=;i<=n;i++)q[++cnt].fir=x[i],q[cnt].sec=t[i],q[cnt].pos=i,q[cnt].ty=;
for(int i=;i<=m;i++)
{
q[++cnt].fir=l[i];q[cnt].sec=a[i];q[cnt].trd=b[i];q[cnt].pos=i;q[cnt].ty=;
q[++cnt]=q[cnt-];q[cnt].fir=r[i];q[cnt].ty=-;
}
sort(q+,q++cnt,cmp1);
for(int i=;i<=cnt;i++)
{
if(q[i].ty)add(,,cnt2,q[i].sec,q[i].trd,q[i].ty);
else ans[q[i].pos]=query(,,cnt2,q[i].sec,q[i].sec);
}
for(int i=;i<=n;i++)printf("%d ",ans[i]);printf("\n");
for(int i=;i<=cnt;i++)if(q[i].ty)q[i].ty=(q[i].ty==-)?:-;
memset(tree,,sizeof(tree));sort(q+,q++cnt,cmp2);
for(int i=;i<=cnt;i++)
{
if(q[i].ty)ans[q[i].pos]=(q[i].ty==)?query(,,cnt2,q[i].sec,q[i].trd)-ans[q[i].pos]:query(,,cnt2,q[i].sec,q[i].trd);
else add2(,,cnt2,q[i].sec,);
}
for(int i=;i<=m;i++)printf("%d ",ans[i]);
}
BIT:
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=,inf=1e9;
struct poi{int fir,sec,trd,pos,ty;}q[maxn*];
int n,m,cnt,cnt2,N;
int x[maxn],t[maxn],T[maxn],y[maxn],lisan[maxn],l[maxn],r[maxn],a[maxn],b[maxn],ans[maxn],tree[maxn];
void read(int &k)
{
int f=;k=;char c=getchar();
while(c<''||c>'')c=='-'&&(f=-),c=getchar();
while(c<=''&&c>='')k=k*+c-'',c=getchar();
k*=f;
}
bool cmp1(poi a,poi b){return a.fir==b.fir?a.ty>b.ty:a.fir<b.fir;}
bool cmp2(poi a,poi b){return a.fir==b.fir?(a.ty==b.ty?a.sec<b.sec:a.ty<b.ty):a.fir<b.fir;}
int lowbit(int x){return x&-x;}
void add(int x,int delta){for(;x<=cnt2;x+=lowbit(x))tree[x]+=delta;}
int query(int x){int ans=;for(;x;x-=lowbit(x))ans+=tree[x];return ans;}
int main()
{
read(n);read(m);
for(int i=;i<=n;i++)read(t[i]),read(x[i]),lisan[++cnt2]=t[i];
for(int i=;i<=m;i++)read(T[i]),read(l[i]),read(r[i]),read(y[i]);
for(int i=;i<=m;i++)a[i]=T[i]-y[i],b[i]=T[i]+y[i];
for(int i=;i<=m;i++)lisan[++cnt2]=a[i],lisan[++cnt2]=b[i];
N=cnt2;N=unique(lisan+,lisan++N)-lisan-;sort(lisan+,lisan++N);
for(int i=;i<=m;i++)
{
a[i]=lower_bound(lisan+,lisan++N,a[i])-lisan;
b[i]=lower_bound(lisan+,lisan++N,b[i])-lisan;
}
for(int i=;i<=n;i++)
t[i]=lower_bound(lisan+,lisan++N,t[i])-lisan;
for(int i=;i<=n;i++)q[++cnt].fir=x[i],q[cnt].sec=t[i],q[cnt].pos=i,q[cnt].ty=;
for(int i=;i<=m;i++)
{
q[++cnt].fir=l[i];q[cnt].sec=a[i];q[cnt].trd=b[i];q[cnt].pos=i;q[cnt].ty=;
q[++cnt]=q[cnt-];q[cnt].fir=r[i];q[cnt].ty=-;
}
sort(q+,q++cnt,cmp1);
for(int i=;i<=cnt;i++)
{
if(q[i].ty)add(q[i].sec,q[i].ty),add(q[i].trd+,-q[i].ty);
else ans[q[i].pos]=query(q[i].sec);
}
for(int i=;i<=n;i++)printf("%d ",ans[i]);printf("\n");
for(int i=;i<=cnt;i++)if(q[i].ty)q[i].ty=(q[i].ty==-)?:-;
memset(tree,,(cnt2+)<<);sort(q+,q++cnt,cmp2);
for(int i=;i<=cnt;i++)
{
if(q[i].ty)ans[q[i].pos]=(q[i].ty==)?query(q[i].trd)-query(q[i].sec-)-ans[q[i].pos]:query(q[i].trd)-query(q[i].sec-);
else add(q[i].sec,);
}
for(int i=;i<=m;i++)printf("%d ",ans[i]);
}
SRM13绵津见-终(扫描线+线段树/BIT)的更多相关文章
- HDU 3642 - Get The Treasury - [加强版扫描线+线段树]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3642 Time Limit: 10000/5000 MS (Java/Others) Memory L ...
- 【BZOJ3958】[WF2011]Mummy Madness 二分+扫描线+线段树
[BZOJ3958][WF2011]Mummy Madness Description 在2011年ACM-ICPC World Finals上的一次游览中,你碰到了一个埃及古墓. 不幸的是,你打开了 ...
- HDU 3265/POJ 3832 Posters(扫描线+线段树)(2009 Asia Ningbo Regional)
Description Ted has a new house with a huge window. In this big summer, Ted decides to decorate the ...
- 【bzoj4491】我也不知道题目名字是什么 离线扫描线+线段树
题目描述 给定一个序列A[i],每次询问l,r,求[l,r]内最长子串,使得该子串为不上升子串或不下降子串 输入 第一行n,表示A数组有多少元素接下来一行为n个整数A[i]接下来一个整数Q,表示询问数 ...
- hdu1542 Atlantis(扫描线+线段树+离散)矩形相交面积
题目链接:点击打开链接 题目描写叙述:给定一些矩形,求这些矩形的总面积.假设有重叠.仅仅算一次 解题思路:扫描线+线段树+离散(代码从上往下扫描) 代码: #include<cstdio> ...
- P3722 [AH2017/HNOI2017]影魔(单调栈+扫描线+线段树)
题面传送门 首先我们把这两个贡献翻译成人话: 区间 \([l,r]\) 产生 \(p_1\) 的贡献当且仅当 \(a_l,a_r\) 分别为区间 \([l,r]\) 的最大值和次大值. 区间 \([l ...
- BZOJ 2584: [Wc2012]memory(扫描线+线段树)
题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=2584 题意:给出平面n个线段,任意两个线段严格不相交,且每个线段不平行于坐标轴.移 ...
- [BZOJ 1218] [HNOI2003] 激光炸弹 【n logn 做法 - 扫描线 + 线段树】
题目链接:BZOJ - 1218 题目分析 可以覆盖一个边长为 R 的正方形,但是不能包括边界,所以等价于一个边长为 R - 1 的正方形. 坐标范围 <= 5000 ,直接 n^2 的二维前缀 ...
- hdu4419 Colourful Rectangle 12年杭州网络赛 扫描线+线段树
题意:给定n个矩形,每个矩形有一种颜色,RGB中的一种.相交的部分可能为RG,RB,GB,RGB,问这n个矩形覆盖的面积中,7种颜色的面积分别为多少 思路:把x轴离散化做扫描线,线段树维护一个扫描区间 ...
随机推荐
- wordlist 4
wordlist 4 desolate 啥啥啥lete adj. 荒凉的:无人烟的 repression depression n. 抑制,[心理] 压抑:镇压 / n. 沮丧:忧愁:抑郁症: spe ...
- Unity编辑器 - 编辑器控制特效播放
编辑器控制特效播放 Unity的动画编辑器不能预览粒子系统的播放,为了方便预览特效,设想制作一个预览特效的工具,通常一个特效有三种组件: - Animation - Animator - Partic ...
- (C#)原型模式—深复制与浅复制
1.原型模式 用原型实例指定创建对象的实例,并且通过拷贝这些原型创建新的对象. *原型模式隐藏了创建对象的细节,提高了性能. *浅复制:被复制对象的所有变量都含有与原来对象相同的值,而且所有对其他对象 ...
- 浅谈如何写出一个让(坑)人(王)很(之)难(王)发现的bug
该文章内容来自脚本之家,原文链接:https://www.jb51.net/news/598404.html 程序员的日常三件事:写bug.改bug.背锅.连程序员都自我调侃道,为什么每天都在加班?因 ...
- Wordcount -- MapReduce example -- Reducer
Reducer receives (key, values) pairs and aggregate values to a desired format, then write produced ( ...
- JavaScript筑基篇(一)->变量、值与对象
说明 JavaScript中变量.值.对象的理解.本文为了简化理解,前半部分暂时刨除与执行上下文的相关概念.另外本文是个人的见解,如有疑问或不正支持,欢迎提出指正和讨论! 目录 前言 参考来源 变量与 ...
- 常用算法Java实现之选择排序
选择排序算法在每一步中选取最小值来重新排序,通过选择和交换来实现排序. 具体流程如下: 1.首先从原数组中选择最小的1个数据,将其置于第一个位置. 2.然后从剩下的数据中再选择其中最小的一个数据,并将 ...
- Internet History,Tecchnology and Security
Internet History Internet Technologe Internet Secure
- python学习摘要(2)--基本数据类型
python申请存储空间是动态的.变量如同指针一样指向存储空间.多个变量会指向同一个存储空间(节省空间).当变量改变时,原来的地址单元并不会马上释放.(引用计数自行回收) c/c++根基性语言,想要什 ...
- HDU 2163 Palindromes
http://acm.hdu.edu.cn/showproblem.php?pid=2163 Problem Description Write a program to determine whet ...