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轴离散化做扫描线,线段树维护一个扫描区间 ...
随机推荐
- JavaScript基本概念(1)-声明提升
声明提升: function > var > other var提升的时候,只是声明提升,但是赋值还是会在原来的位置. Javascript Hoisting:In javascript, ...
- 打印队列 (Printer Queue,ACM/ICPC NWERC 2006,UVA12100)
题目描述: 题目思路: 使用一个队列记录数字,一个优先队列记录优先级,如果相等即可打印: #include <iostream> #include <queue> using ...
- 从零开始的Python学习Episode 3——字符串格式化与for循环
一.字符串格式化 利用一段注释记录想要输出的字符串格式,并用 %s . %d 或 %f 依次代替要输出的数据(%s代表字符串,%d代表数字,%f代表浮点数),然后在这段注释之后依次加上要输出的数据. ...
- CPU设计学习-流水线
各种名词 标量流水线 超级流水线 超标量流水线与多发射技术 经典五级流水线 IF |Instruction Fetch,取指 ID |Instruction Decode,译码 EX |Execute ...
- LeetCode 144 ——二叉树的前序遍历
1. 题目 2. 解答 2.1. 递归法 定义一个存放树中数据的向量 data,从根节点开始,如果节点不为空,那么 将当前节点的数值加入到 data 中 递归得到其左子树的数据向量 temp,将 te ...
- Python3.5 Keras-Theano(含其他库)windows 安装环境
https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/Anaconda3-4.2.0-Windows-x86.execonda --version ...
- Python实现个性化推荐一
现如今,网站用推荐系统为你提供个性化的体验,告诉你买啥,吃啥甚至你应该和谁交朋友.尽管每个人口味不同,但大体都适用这个套路.人们倾向于喜欢那些与自己喜欢的其他东西相似的东西,也倾向于与自己身边的人有相 ...
- Linux error:No space left on device
一台Oracle数据库服务器在关机重启后,Oracle监听无法启动,提示错误 Linux error:no space left on device 提示可知:问题是出在磁盘空间不足 但是初步查看分区 ...
- HDU 2489 Minimal Ratio Tree(暴力+最小生成树)(2008 Asia Regional Beijing)
Description For a tree, which nodes and edges are all weighted, the ratio of it is calculated accord ...
- 20145214《Java程序设计》课程总结
20145214<Java程序设计>课程总结 每周读书笔记链接汇总 第一周读书笔记 第二周读书笔记 第三周读书笔记 第四周读书笔记 第五周读书笔记 第六周读书笔记 第七周读书笔记 第八周读 ...