敌人
(
x
,
y
)
(x,y)
(x,y)能被
(
x
m
,
y
m
)
(x_m,y_m)
(xm,ym)打中当且仅当:
y
m
−
x
−
x
m
2
≤
y
≤
y
m
+
x
−
x
m
2
y_m- \frac{x-x_m}{2}\leq y\leq y_m+\frac{x-x_m}{2}
ym−2x−xm≤y≤ym+2x−xm
我们化简一下这个不等式,
x
,
y
x,y
x,y放一边,
x
m
,
y
m
x_m,y_m
xm,ym放一边:
{
2
y
−
x
≤
2
y
m
−
x
m
−
2
y
−
x
≤
−
2
y
m
−
x
m
\begin{cases} ~~2y-x\leq2y_m-x_m\\ -2y-x\leq-2y_m-x_m\\ \end{cases}
{ 2y−x≤2ym−xm−2y−x≤−2ym−xm
好了,那么显然就是一个二维偏序的问题。
那么关键就在于如何快速的求出所有点。
可以在维护val(离散化后 2 y − x 2y-x 2y−x的个数)个桶,每个桶里面装点的标号和 − 2 y − x -2y-x −2y−x,用bit或者线段树找到所有的合法点即可。
树状数组和线段树的写法本质都是一样的:
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
#define fi first
#define se second
#define pb push_back
#define wzh(x) cerr<<#x<<'='<<x<<endl;
const int mod=1e9+7;
int add(int x,int y){
x+=y;
if(x>=mod)x-=mod;
if(x<0)x+=mod;
return x;
}
int mul(int x,int y){
return 1ll*x*y%mod;
}
int sub(int x,int y){
x=x+mod-y;
if(x>=mod)x-=mod;
return x;
}
//mod_int
int n,q;
vector<LL>dx,dy;
pair<LL,LL>po[N];
struct bit{
vector<pair<int,int>>t[N];
void Add(int x,int y,int i){
for(;x<N;x+=x&-x)t[x].emplace_back(y,i);
}
int get(int x,int y){
vector<int>v;
for(;x;x-=x&-x){
for(auto k:t[x]){
if(k.fi<y){
v.pb(k.se);
}else break;
}
}
sort(v.begin(),v.end());
int ans=0,pop=5782344,now=1;
for(auto k:v){
ans=add(ans,mul(now,k));
now=mul(now,pop);
}
return ans;
}
}T;
int main() {
ios::sync_with_stdio(false);
cin>>n>>q;
for(int i=1;i<=n;i++){
LL x,y;
cin>>x>>y;
LL xx=-x-2*y,yy=-x+2*y;
dx.pb(xx);
dy.pb(yy);
po[i]={xx,yy};
}
sort(dx.begin(),dx.end());
sort(dy.begin(),dy.end());
dx.erase(unique(dx.begin(),dx.end()),dx.end());
dy.erase(unique(dy.begin(),dy.end()),dy.end());
for(int i=1;i<=n;i++){
po[i].fi=lower_bound(dx.begin(),dx.end(),po[i].fi)-dx.begin();
po[i].se=lower_bound(dy.begin(),dy.end(),po[i].se)-dy.begin();
T.Add(po[i].fi+1,po[i].se,i);
}
for(int i=0;i<=dx.size();i++){
sort(T.t[i].begin(),T.t[i].end());
}
int last=0;
for(int i=1;i<=q;i++){
LL x,y;
cin>>x>>y;
x=-1-add(last,x);
y=add(last,y);
LL xx=-x-2ll*y,yy=-x+2ll*y;
int dl=upper_bound(dx.begin(),dx.end(),xx)-dx.begin();
int dr=upper_bound(dy.begin(),dy.end(),yy)-dy.begin();
cout<<(last=T.get(dl,dr))<<'\n';
}
return 0;
}
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
#define fi first
#define se second
#define pb push_back
#define wzh(x) cerr<<#x<<'='<<x<<endl;
const int mod=1e9+7;
int add(int x,int y){
x+=y;
if(x>=mod)x-=mod;
if(x<0)x+=mod;
return x;
}
int mul(int x,int y){
return 1ll*x*y%mod;
}
int sub(int x,int y){
x=x+mod-y;
if(x>=mod)x-=mod;
return x;
}
//mod_int
int n,q;
vector<LL>dx,dy;
pair<LL,LL>po[N];
struct uzi{
int x,y,pos;
bool operator <(const uzi & t)const{
return x<t.x;
}
}p[N];
vector<pair<int,int>>t[N<<2];
int T[N];
#define mid (l+r>>1)
int cnt;
#define ls o<<1
#define rs o<<1|1
void add(int o,int l,int r,int x,int y,int pos){
t[o].emplace_back(y,pos);
if(l==r)return;
if(x<=mid)add(ls,l,mid,x,y,pos);
else add(rs,mid+1,r,x,y,pos);
}
void build(int o,int l,int r){
sort(t[o].begin(),t[o].end());
if(l==r)return;
build(ls,l,mid);
build(rs,mid+1,r);
}
vector<int>cur;
void get(int o,int l,int r,int x,int y,int dx){
if(l>=x&&r<=y){
for(auto k:t[o]){
if(k.fi<=dx)cur.emplace_back(k.se);
else break;
}
return;
}
if(x<=mid)get(ls, l , mid,x,y ,dx);
if(y>mid)get(rs,mid+1,r,x,y,dx);
}
int val;
int get_ans(int x,int y){
cur.clear();
get(1,0,val,1,x,y);
sort(cur.begin(),cur.end());
int ans=0,base=5782344,now=1;
for(auto k:cur){
ans=add(ans,mul(k,now));
now=mul(now,base);
}
return ans;
}
int main() {
ios::sync_with_stdio(false);
cin>>n>>q;
for(int i=1;i<=n;i++){
LL x,y;
cin>>x>>y;
LL xx=-x-2*y,yy=-x+2*y;
dx.pb(xx);
dy.pb(yy);
po[i]={xx,yy};
}
sort(dx.begin(),dx.end());
sort(dy.begin(),dy.end());
dx.erase(unique(dx.begin(),dx.end()),dx.end());
dy.erase(unique(dy.begin(),dy.end()),dy.end());
for(int i=1;i<=n;i++){
po[i].fi=lower_bound(dx.begin(),dx.end(),po[i].fi)-dx.begin();
po[i].se=lower_bound(dy.begin(),dy.end(),po[i].se)-dy.begin();
p[i]={(int)po[i].fi+1,(int)po[i].se+1,i};
}
sort(p+1,p+1+n);
val=dx.size();
for(int i=1;i<=n;i++){
add(1, 0, val, p[i].x, p[i].y, p[i].pos);
}
build(1,0,val);
int last=0;
auto find=[&](int x){
int l=1,r=n,ok=0;
while(l<=r){
if(p[mid].x<=x)ok=mid,l=mid+1;
else r=mid-1;
}
return ok;
};
for(int i=1;i<=q;i++){
LL x,y;
cin>>x>>y;
x=-1-add(last,x);
y=add(last,y);
LL xx=-x-2ll*y,yy=-x+2ll*y;
int dl=upper_bound(dx.begin(),dx.end(),xx)-dx.begin();
int dr=upper_bound(dy.begin(),dy.end(),yy)-dy.begin();
cout<<(last=get_ans(dl,dr))<<'\n';
}
return 0;
}