思路:对于每个询问来说,每一个
u
u
u,只存在一个
v
v
v使得
F
(
u
,
v
)
=
C
i
F(u,v)=C_i
F(u,v)=Ci。
那么提前将点按
x
x
x坐标排好序,枚举
u
u
u,将
x
≤
u
x\le u
x≤u的点放入BIT,用树状数组记录点的个数及
x
+
y
x+y
x+y的值,然后二分
v
v
v。
二分时用树状数组计算
F
(
u
,
v
)
F(u,v)
F(u,v)。
PS:当
C
i
>
2
∗
1
0
10
C_i>2*10^{10}
Ci>2∗1010时,显然无解;没优化这个之前,一直TLE。。
#include<bits/stdc++.h>
using namespace std;
const int MAX=1e5+10;
const int MOD=1e9+7;
const int INF=1e9+7;
const double PI=acos(-1.0);
typedef long long ll;
struct Point{int x,y;}p[MAX];
int cmp(const Point&A,const Point &B){return A.x<B.x;}
ll A[MAX],B[MAX];
ll C[11],ans[11];
int n,m;
void add(int x,int y)
{
while(x<=n)
{
A[x]++;
B[x]+=y;
x+=x&(-x);
}
}
ll cal(int x,int y)
{
ll ans=0,cnt=0;
int Q=y;
while(Q){cnt+=A[Q];ans+=B[Q];Q-=Q&(-Q);}
return cnt*(x+y)-ans;
}
int main()
{
int T;
cin>>T;
while(T--)
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)scanf("%d%d",&p[i].x,&p[i].y);
sort(p+1,p+m+1,cmp);
int QWQ;
scanf("%d",&QWQ);
for(int i=1;i<=QWQ;i++)scanf("%lld",&C[i]);
memset(ans,0,sizeof ans);
int R=1;
for(int i=1;i<=n;i++)A[i]=B[i]=0;
for(int x=1;x<=n;x++)
{
while(R<=m&&p[R].x<=x)
{
add(p[R].y,p[R].y+p[R].x);
R++;
}
for(int i=1;i<=QWQ;i++)
{
if(C[i]>=2e10)continue;
int l=1,r=n;
if(cal(x,n)<C[i])continue;
if(cal(x,1)>C[i])continue;
while(r>=l)
{
int mid=(l+r)/2;
ll Back=cal(x,mid);
if(Back>C[i])r=mid-1;
else if(Back==C[i])
{
ans[i]++;
break;
}
else l=mid+1;
}
}
}
for(int i=1;i<=QWQ;i++)printf("%lld%c",ans[i],i==QWQ?'\n':' ');
}
return 0;
}