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轴离散化做扫描线,线段树维护一个扫描区间 ...
随机推荐
- Qt-QML-给我的导航条写一个动画-State-Transition
上篇中,我已经写出一个导航条的,虽然太丑了,不过功能是有了,这次我将要给我的导航条加一个动画,先看下演示效果 这次我是用的是一个状态动画,大致原理就是写出一个空间的几个状态,完了再加一个过度动画,这里 ...
- MySQL☞in语句
in语句: 1)列名 in(数值1,数值2,数值3…):求出满足该列的多个列值 格式: select 列名1,列名2 from 表名 where 列名 in (数值1,数值2,数值3...) 如下图 ...
- ortp代码简析
ortp初始化 /** * Initialize the oRTP library. You should call this function first before using * ...
- 定时任务 linux crontab 学习整理
1. 定时任务命令概念 crontab命令用于设置周期性被执行的指令.即设定脚本 按照规定时间执行相关的操作. 2.定时任务书写规范 * * * ...
- 【转】unity3d 资源文件从MAX或者MAYA中导出的注意事项
转自游戏开发主席 1.首先,Unity3d 中,导出带动画的资源有2种导出方式可以选择: 1) 导出资源时,只导出一个文件,保留模型,骨骼和所有的动作帧(把所有的动作,比如idle,atta ...
- springmvc项目,浏览器报404错误的问题
问题描述: 建立了web工程,配置pom.xml,web.xml,编写controller类,在spring-mvc-servlet.xml文件中指定开启注解和扫描的包位置<mvc:annota ...
- Linux内核设计笔记13——虚拟文件系统
虚拟文件系统 内核在它的底层文件系统系统接口上建立一个抽象层,该抽象层使Linux可以支持各种文件系统,即便他们在功能和行为上存在很大差异. VFS抽象层定义了各个文件系统都支持的基本的.概念上的接口 ...
- javascript对table的添加,删除行的操作
<body> <form name="myForm"> <table width="100%" id="tab" ...
- Thunder团队第二周 - Scrum会议7
Scrum会议7 小组名称:Thunder 项目名称:i阅app Scrum Master:杨梓瑞 工作照片: 参会成员: 王航:http://www.cnblogs.com/wangh013/ 李传 ...
- 20145214 《Java程序设计》第9周学习总结
20145214 <Java程序设计>第9周学习总结 教材学习内容总结 JDBC简介 JDBC全名Java DataBase Connectivity,是java联机数据库的标准规范.它定 ...