题目大意:求对于每个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)的更多相关文章

  1. HDU 3642 - Get The Treasury - [加强版扫描线+线段树]

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3642 Time Limit: 10000/5000 MS (Java/Others) Memory L ...

  2. 【BZOJ3958】[WF2011]Mummy Madness 二分+扫描线+线段树

    [BZOJ3958][WF2011]Mummy Madness Description 在2011年ACM-ICPC World Finals上的一次游览中,你碰到了一个埃及古墓. 不幸的是,你打开了 ...

  3. 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 ...

  4. 【bzoj4491】我也不知道题目名字是什么 离线扫描线+线段树

    题目描述 给定一个序列A[i],每次询问l,r,求[l,r]内最长子串,使得该子串为不上升子串或不下降子串 输入 第一行n,表示A数组有多少元素接下来一行为n个整数A[i]接下来一个整数Q,表示询问数 ...

  5. hdu1542 Atlantis(扫描线+线段树+离散)矩形相交面积

    题目链接:点击打开链接 题目描写叙述:给定一些矩形,求这些矩形的总面积.假设有重叠.仅仅算一次 解题思路:扫描线+线段树+离散(代码从上往下扫描) 代码: #include<cstdio> ...

  6. P3722 [AH2017/HNOI2017]影魔(单调栈+扫描线+线段树)

    题面传送门 首先我们把这两个贡献翻译成人话: 区间 \([l,r]\) 产生 \(p_1\) 的贡献当且仅当 \(a_l,a_r\) 分别为区间 \([l,r]\) 的最大值和次大值. 区间 \([l ...

  7. BZOJ 2584: [Wc2012]memory(扫描线+线段树)

    题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=2584 题意:给出平面n个线段,任意两个线段严格不相交,且每个线段不平行于坐标轴.移 ...

  8. [BZOJ 1218] [HNOI2003] 激光炸弹 【n logn 做法 - 扫描线 + 线段树】

    题目链接:BZOJ - 1218 题目分析 可以覆盖一个边长为 R 的正方形,但是不能包括边界,所以等价于一个边长为 R - 1 的正方形. 坐标范围 <= 5000 ,直接 n^2 的二维前缀 ...

  9. hdu4419 Colourful Rectangle 12年杭州网络赛 扫描线+线段树

    题意:给定n个矩形,每个矩形有一种颜色,RGB中的一种.相交的部分可能为RG,RB,GB,RGB,问这n个矩形覆盖的面积中,7种颜色的面积分别为多少 思路:把x轴离散化做扫描线,线段树维护一个扫描区间 ...

随机推荐

  1. adb获取设备的序列号

    用数据线连接手机, 打开开发者模式, 并赋予相关权限, 在CMD命令行输入: adb devices 第一个参数即为设备的序列号, 第二个参数device表示设备的状态是在线.

  2. ObjectMapper的使用

    Jackson ObjectMapper类 ObjectMapper类是Jackson库的主要类它提供一些功能将Java对象转换成JSON结构,反之亦然它使用JsonParser和JsonGenera ...

  3. 哈希表 -数据结构(C语言实现)

    读数据结构与算法分析 哈希表 一种用于以常数平均时间执行插入.删除和查找操作的数据结构. 但是是无序的 一般想法 通常为一个包含关键字的具有固定大小的数组 每个关键字通过散列函数映射到数组中 冲突:两 ...

  4. 树(Tree,UVA 548)

    题目描述: 题目思路: 1.使用数组建树 //递归 2.理解后序遍历和中序遍历,建立左右子树 3.dfs深度搜索找出权重最小的路径 #include <iostream> #include ...

  5. 计蒜客蓝桥杯模拟赛 后缀字符串:STL_map+贪心

    问题描述 一天蒜头君得到 n 个字符串 si​,每个字符串的长度都不超过 10. 蒜头君在想,在这 n 个字符串中,以 si​ 为后缀的字符串有多少个呢? 输入格式 第一行输入一个整数 n. 接下来  ...

  6. Ubuntu 16.04 安装显卡驱动后循环登录和无法设置分辨率的一种解决方案

    1. 安装环境 电脑:MSI GP63 显卡:GeForce GTX 1070 系统:Ubuntu 16.04 驱动版本:NVIDIA 384.130 2. 循环登录 如果按照这篇文章 Ubuntu ...

  7. Hadoop第一课:Hadoop集群环境搭建

    一. 检查列表 1.1.网络访问 设置电脑IP以及可以访问网络设置:进入etc/sysconfig/network-scripts/,使用命令“ls -all” 查看文件.会看到ifcfg-lo文件然 ...

  8. mouseover 和 mouseout 事件是可以冒泡的 取消

    mouseover 和 mouseout 事件是可以冒泡的,子元素上触发的事件会冒泡到父元素上.可以改用 mouseleave 和 mouseenter 事件,这两个事件不冒泡.

  9. 关于docker 基础使用记录

    Docker Hub地址:https://hub.docker.com Docker Hub 存放着 Docker 及其组件的所有资源.Docker Hub 可以帮助你与同事之间协作,并获得功能完整的 ...

  10. Median Weight Bead(最短路—floyed传递闭包)

    Description There are N beads which of the same shape and size, but with different weights. N is an ...