没有看懂差分做法,来一个暴力拆式子+数据结构做法。
考虑 ,然后你就发现都可以归约为
,考虑中间情况,当其为
或
时候的贡献满足上面的式子,只有为
的时候上面的式子会算错,所以对于一个固定的
,你考虑其答案为
,其中
表示有多少个
满足
或
,而
很好处理,只需要考虑
即可,考虑把
看成线段
,显然
不跨过其中点的时候,
,反之为
,又因为
是整数,所以可以考虑中点为
,接下来思路就比较清晰了,你考虑对于每一对
,存他们的中点
,绑定在一起,然后按照中点从大到小排序,对于每个
,都可以考虑分成两类,因为是从大到小排序,所以一定会有
和
两个类别,对于
的,肯定取
,然后你考虑把这里面的
按照
的和
的分开,进行绝对值化简。对于
的,肯定取
,进行同理的拆分。
然后你发现这样的话复杂度是 ,还是超时,但是你发现,如果我们按照
从小到大处理,那么
和
的分界线一定会越来越往前,所以我们考虑不用每次都重新记录,直接从上一次没记录完的位置到当前继续记录,先考虑
,此时的话我们只需要知道小于等于
的
的个数和他们的和,就可以算出
,
的同理。
而维护这个东西可以树状数组(一个维护权值,一个维护个数),处理分界线可以二分,所以对于每个 只要算
就可以了,把答案存下来,可以
询问,时间复杂度
。
更多细节或者不懂的地方可以看代码:
#include<bits/stdc++.h>
#define ll long long
#define db double
#define vec vector
#define pb push_back
#define pll pair<ll,ll>
#define mkp make_pair
#define il inline
#define endl "\n"
using namespace std;
const ll mod=998244353;
const ll inf=1e18;
ll n,q,a[200005],b[200005],cnt[200005],ans[200005];
struct BIT{
ll c[200005];
ll lb(ll x){
return x&(-x);
}
void add(ll x,ll y){
for(ll i=x;i<=n;i+=lb(i)) c[i]+=y;
}
ll sum(ll x){
ll res=0;
for(ll i=x;i;i-=lb(i)) res+=c[i];
return res;
}
}tr1,tr2,tr3,tr4;
struct dat{
ll a,b,m;
}p[200005];
bool cmp(dat x,dat y){
return x.m>y.m;
}
ll sa(ll l,ll r){
if(l>r) return 0;
return a[r]-a[l-1];
}
ll sb(ll l,ll r){
if(l>r) return 0;
return b[r]-b[l-1];
}
ll bs(ll x){
if(x>p[1].m) return 1;
if(p[n].m>=x) return n+1;
ll l=1,r=n,res=0;
while(l<=r){
ll md=(l+r)>>1;
if(p[md].m<x){
r=md-1,res=md;
}else{
l=md+1;
}
}
return res;
}
void solve(){
cin>>n>>q;
for(ll i=1;i<=n;i++) tr1.c[i]=tr2.c[i]=tr3.c[i]=tr4.c[i]=cnt[i]=ans[i]=0;
for(ll i=1;i<=n;i++) cin>>p[i].a>>p[i].b,p[i].m=(p[i].a+p[i].b)>>1,cnt[p[i].a]++,cnt[p[i].b]++,cnt[p[i].a]-=(p[i].a==p[i].b);
sort(p+1,p+n+1,cmp);ll rt=n+1;
for(ll i=1;i<=n;i++) tr1.add(p[i].a,1),tr2.add(p[i].a,p[i].a),a[i]=a[i-1]+p[i].a,b[i]=b[i-1]+p[i].b;
for(ll i=1;i<=n;i++){
ll pos=bs(i);
for(ll j=pos;j<rt;j++) tr1.add(p[j].a,-1),tr2.add(p[j].a,-p[j].a),tr3.add(p[j].b,1),tr4.add(p[j].b,p[j].b);
rt=pos;
ll c1=tr1.sum(i),s1=tr2.sum(i),c2=tr3.sum(i),s2=tr4.sum(i);
ll s3=sa(1,pos-1)-s1-(pos-1-c1)*i+c1*i-s1;
ll s4=sb(pos,n)-s2-(n-pos+1-c2)*i+c2*i-s2;
ans[i]=s3+s4-n+cnt[i];
}
while(q--){
ll x;cin>>x;
cout<<ans[x]<<" ";
}
cout<<endl;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
ll T;cin>>T;
while(T--) solve();
return 0;
}

京公网安备 11010502036488号