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=500010,inf=1e9;
struct tjm{int sum,delta;}tree[maxn*4];
struct poi{int fir,sec,trd,pos,ty;}q[maxn*4];
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=1;k=0;char c=getchar();
    while(c<‘0‘||c>‘9‘)c==‘-‘&&(f=-1),c=getchar();
    while(c<=‘9‘&&c>=‘0‘)k=k*10+c-‘0‘,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<<1].sum+tree[x<<1|1].sum;}
inline void pushdown(int x)
{
    if(!tree[x].delta)return;
    tree[x<<1].delta+=tree[x].delta;tree[x<<1|1].delta+=tree[x].delta;
    tree[x<<1].sum+=tree[x].delta;tree[x<<1|1].sum+=tree[x].delta;
    tree[x].delta=0;
}
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)>>1;
    if(cl<=mid)add(x<<1,l,mid,cl,cr,delta);
    if(cr>mid)add(x<<1|1,mid+1,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)>>1;
    if(cx<=mid)add2(x<<1,l,mid,cx,delta);
    else add2(x<<1|1,mid+1,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)>>1,ans=0;
    if(cl<=mid)ans+=query(x<<1,l,mid,cl,cr);
    if(cr>mid)ans+=query(x<<1|1,mid+1,r,cl,cr);
    return ans;
}
int main()
{
    read(n);read(m);
    for(int i=1;i<=n;i++)read(t[i]),read(x[i]),lisan[++cnt2]=t[i];
    for(int i=1;i<=m;i++)read(T[i]),read(l[i]),read(r[i]),read(y[i]);
    for(int i=1;i<=m;i++)a[i]=T[i]-y[i],b[i]=T[i]+y[i];
    for(int i=1;i<=m;i++)lisan[++cnt2]=a[i],lisan[++cnt2]=b[i];
    N=cnt2;N=unique(lisan+1,lisan+1+N)-lisan-1;sort(lisan+1,lisan+1+N);
    for(int i=1;i<=m;i++)
    {
        a[i]=lower_bound(lisan+1,lisan+1+N,a[i])-lisan;
        b[i]=lower_bound(lisan+1,lisan+1+N,b[i])-lisan;
    }
    for(int i=1;i<=n;i++)
    t[i]=lower_bound(lisan+1,lisan+1+N,t[i])-lisan;
    for(int i=1;i<=n;i++)q[++cnt].fir=x[i],q[cnt].sec=t[i],q[cnt].pos=i,q[cnt].ty=0;
    for(int i=1;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=1;
        q[++cnt]=q[cnt-1];q[cnt].fir=r[i];q[cnt].ty=-1;
    }
    sort(q+1,q+1+cnt,cmp1);
    for(int i=1;i<=cnt;i++)
    {
        if(q[i].ty)add(1,1,cnt2,q[i].sec,q[i].trd,q[i].ty);
        else ans[q[i].pos]=query(1,1,cnt2,q[i].sec,q[i].sec);
    }
    for(int i=1;i<=n;i++)printf("%d ",ans[i]);printf("\n");
    for(int i=1;i<=cnt;i++)if(q[i].ty)q[i].ty=(q[i].ty==-1)?2:-1;
    memset(tree,0,sizeof(tree));sort(q+1,q+1+cnt,cmp2);
    for(int i=1;i<=cnt;i++)
    {
        if(q[i].ty)ans[q[i].pos]=(q[i].ty==2)?query(1,1,cnt2,q[i].sec,q[i].trd)-ans[q[i].pos]:query(1,1,cnt2,q[i].sec,q[i].trd);
        else add2(1,1,cnt2,q[i].sec,1);
    }
    for(int i=1;i<=m;i++)printf("%d ",ans[i]);
}

BIT:

#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=500010,inf=1e9;
struct poi{int fir,sec,trd,pos,ty;}q[maxn*4];
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=1;k=0;char c=getchar();
    while(c<‘0‘||c>‘9‘)c==‘-‘&&(f=-1),c=getchar();
    while(c<=‘9‘&&c>=‘0‘)k=k*10+c-‘0‘,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=0;for(;x;x-=lowbit(x))ans+=tree[x];return ans;}
int main()
{
    read(n);read(m);
    for(int i=1;i<=n;i++)read(t[i]),read(x[i]),lisan[++cnt2]=t[i];
    for(int i=1;i<=m;i++)read(T[i]),read(l[i]),read(r[i]),read(y[i]);
    for(int i=1;i<=m;i++)a[i]=T[i]-y[i],b[i]=T[i]+y[i];
    for(int i=1;i<=m;i++)lisan[++cnt2]=a[i],lisan[++cnt2]=b[i];
    N=cnt2;N=unique(lisan+1,lisan+1+N)-lisan-1;sort(lisan+1,lisan+1+N);
    for(int i=1;i<=m;i++)
    {
        a[i]=lower_bound(lisan+1,lisan+1+N,a[i])-lisan;
        b[i]=lower_bound(lisan+1,lisan+1+N,b[i])-lisan;
    }
    for(int i=1;i<=n;i++)
    t[i]=lower_bound(lisan+1,lisan+1+N,t[i])-lisan;
    for(int i=1;i<=n;i++)q[++cnt].fir=x[i],q[cnt].sec=t[i],q[cnt].pos=i,q[cnt].ty=0;
    for(int i=1;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=1;
        q[++cnt]=q[cnt-1];q[cnt].fir=r[i];q[cnt].ty=-1;
    }
    sort(q+1,q+1+cnt,cmp1);
    for(int i=1;i<=cnt;i++)
    {
        if(q[i].ty)add(q[i].sec,q[i].ty),add(q[i].trd+1,-q[i].ty);
        else ans[q[i].pos]=query(q[i].sec);
    }
    for(int i=1;i<=n;i++)printf("%d ",ans[i]);printf("\n");
    for(int i=1;i<=cnt;i++)if(q[i].ty)q[i].ty=(q[i].ty==-1)?2:-1;
    memset(tree,0,(cnt2+1)<<2);sort(q+1,q+1+cnt,cmp2);
    for(int i=1;i<=cnt;i++)
    {
        if(q[i].ty)ans[q[i].pos]=(q[i].ty==2)?query(q[i].trd)-query(q[i].sec-1)-ans[q[i].pos]:query(q[i].trd)-query(q[i].sec-1);
        else add(q[i].sec,1);
    }
    for(int i=1;i<=m;i++)printf("%d ",ans[i]);
}

  

时间: 2024-10-06 01:15:08

SRM13绵津见-终(扫描线+线段树/BIT)的相关文章

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

题目链接:点击打开链接 题目描写叙述:给定一些矩形,求这些矩形的总面积.假设有重叠.仅仅算一次 解题思路:扫描线+线段树+离散(代码从上往下扫描) 代码: #include<cstdio> #include <algorithm> #define MAXN 110 #define LL ((rt<<1)+1) #define RR ((rt<<1)+2) using namespace std; int n; struct segment{ double l

POJ训练计划1177_Picture(扫描线/线段树+离散)

解题报告 题意: 求矩形周长和. 思路: 左扫上扫,扫过了. #include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <cmath> using namespace std; struct Seg { int lx,rx,ly,ry,h,v; friend bool operator < (Seg a,Seg b) { re

POJ 1151 Atlantis 扫描线+线段树

点击打开链接 Atlantis Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 17252   Accepted: 6567 Description There are several ancient Greek texts that contain descriptions of the fabled island Atlantis. Some of these texts even include maps of pa

poj 1151 Atlantis (离散化 + 扫描线 + 线段树)

题目链接题意:给定n个矩形,求面积并,分别给矩形左上角的坐标和右上角的坐标. 分析: 1 #include <iostream> 2 #include <cstdio> 3 #include <vector> 4 #include <cstring> 5 #include <cstdlib> 6 #include <algorithm> 7 #define LL __int64 8 #define lson l, mid, 2*rt

HDU3265_Posters(扫描线/线段树)

解题报告 题意: 给定的矩形里面有镂空的矩阵,求矩阵面积并. 思路: 直接把一个图形拆成4个矩形,进行面积并. 扫描线+线段树 #include <algorithm> #include <iostream> #include <cstring> #include <cstdio> #define LL __int64 using namespace std; struct Seg { int lx,rx,h,v; friend bool operator

HDU1377_Counting Squares(扫描线/线段树)

解题报告 题意: 矩形面积并. 思路: 扫描线+线段树 #include <algorithm> #include <iostream> #include <cstring> #include <cstdio> using namespace std; struct Seg { int lx,rx,h,v; friend bool operator < (Seg a,Seg b) { return a.h<b.h; } } seg[500000]

HDU1542_Atlantis(扫描线/线段树+离散)

解题报告 题目传送门 题意: 求矩形并面积. 思路: 离散+线段树+扫描线. #include <algorithm> #include <iostream> #include <cstring> #include <cstdio> using namespace std; struct Seg { int v; double h,lx,rx; friend bool operator < (Seg a,Seg b) { return a.h<b

HDU 1255 覆盖的面积 (扫描线 线段树 离散化)

题目链接 题意:中文题意. 分析:纯手敲,与上一道题目很相似,但是刚开始我以为只是把cnt>=0改成cnt>=2就行了,. 但是后来发现当当前加入的线段的范围之前 还有线段的时候就不行了,因为虽然现在都不等于 2,但是之前的那个线段加上现在的已经覆盖2次了. 1 #include <iostream> 2 #include <cstdio> 3 #include <vector> 4 #include <cstring> 5 #include &

HNU12884_Area Coverage(扫描线/线段树+离散化)

解题报告 题目传送门 题意: 又是求面积并 思路: 又是求面积并,还被坑了,题目明明描述的是int坐标,用了double才过... #include <algorithm> #include <iostream> #include <cstring> #include <cstdio> using namespace std; struct Seg { double lx,rx,h; int v; friend bool operator <(Seg