題目大意:求對於每一個i求有多少個合法的j以及j對於幾個i是合法的,合法的定義:l[i]<=x[j]<=r[i],T[i]-y[i]<=t[j]<=T[i]+y[i]。ios
設a[i]=T[i]-y[i],b[i]=T[i]+y[i]。
ide
能夠把題目當作一個(x[i],t[i])的點在多少個左上角爲(l[i],a[i])右下角爲(r[i],b[i])的矩陣中。spa
那麼就從上到下掃每一行,每一行從左到右掃,以橫座標爲線段樹或BIT下標。code
對於詢問每一個點在多少個矩陣中,能夠使用差分,掃到矩陣頂部時+1,矩陣底部時-1(詢問完點後再-1或者矩陣底部下一行-1再詢問點均可以),那麼在掃中間的時候全部點都會+1,單點查詢答案便可。blog
對於詢問每一個矩陣中有多少個點,掃描線加入點,將詢問一個矩陣拆成兩個詢問,掃到矩陣頂部時候記錄下答案,掃到矩陣底部時記錄下答案(記錄完答案再加入這一行的點或者加入下一行的點前統計下一行的答案均可以),二者相減即爲這個矩陣的答案。
get
BIT的話區間修改還須要差分一下。
string
線段樹:it
#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:io
#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]); }