题解:P11763 [IAMOI R1] 家庭矛盾
[IAMOI R1] 家庭矛盾
由于
考虑如何处理
前半部分直接上 Yuno loves sqrt technology II 就行了。对于后半部分做法类似,只需要当莫队往右扩展时,将逆序对数乘上
视
#include<bits/stdc++.h>
#define ll long long
#define pn putchar('\n')
#define mset(a,x) memset(a,x,sizeof a)
#define mcpy(a,b) memcpy(a,b,sizeof a)
#define all(a) a.begin(),a.end()
#define fls() fflush(stdout)
#define int ll
using namespace std;
int re()
{
int x=0;
bool t=1;
char ch=getchar();
while(ch>'9'||ch<'0')
t=ch=='-'?0:t,ch=getchar();
while(ch>='0'&&ch<='9')
x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
return t?x:-x;
}
const int maxn=1e5+5;
struct Qry
{
int l,r,i,ad;
};
int n,Q,m,B;
int a[maxn],b[maxn];
int pf[maxn],pf2[maxn],sf[maxn];
int ans[maxn],ans1[maxn*4],ans2[maxn*4];
vector<Qry>qry;
vector<tuple<int,int,int>>qry1[maxn],qry2[maxn];
struct BIT
{
int tree[maxn];
void add(int x,int ad)
{
for(int i=x;i<=n;i+=i&-i)
tree[i]+=ad;
}
int qry(int x)
{
int ret=0;
for(int i=x;i;i-=i&-i)
ret+=tree[i];
return ret;
}
}bit,bit2;
struct Block
{
int n,B;
int a[maxn],b[maxn];
void clr()
{
mset(a,0);
mset(b,0);
}
void add(int x,int ad)
{
int k=x/B;
for(int i=x;i<k*B+B&&i<=n;i++)
a[i]+=ad;
for(int i=k+1;i*B<=n;i++)
b[i]+=ad;
}
int qry(int x)
{
return a[x]+b[x/B];
}
}blk,blk2;
void lsh()
{
vector<int>b;
for(int i=1;i<=n;i++)
b.push_back(a[i]);
sort(all(b));
b.erase(unique(all(b)),b.end());
for(int i=1;i<=n;i++)
a[i]=lower_bound(all(b),a[i])-b.begin()+1;
blk.n=blk2.n=b.size();
blk.B=blk2.B=sqrt(b.size());
}
signed main()
{
n=re();
for(int i=1;i<=n;i++)
{
a[i]=re();
b[i]=b[i-1]+re();
}
lsh();
Q=re();
for(int i=1;i<=Q;i++)
{
int l=re();
int k=b[l-1]+re();
int r=lower_bound(b+1,b+1+n,k)-b-1;
if(r>=l)
qry.push_back({l,r,i,-1});
r=upper_bound(b+1,b+1+n,k)-b-1;
if(r>=l)
qry.push_back({l,r,i,1});
}
B=sqrt((double)n*n/Q)+1;
sort(all(qry),[](Qry x,Qry y){return x.l/B==y.l/B?x.r<y.r:x.l<y.l;});
int L=1,R=0;
for(auto [l,r,i,ad]:qry)
{
if(l<L)
{
m++;
qry1[R].push_back({l,L-1,m});
L=l;
}
if(R<r)
{
m++;
qry2[L].push_back({R+1,r,m});
R=r;
}
if(L<l)
{
m++;
qry1[R].push_back({L,l-1,m});
L=l;
}
if(r<R)
{
m++;
qry2[L].push_back({r+1,R,m});
R=r;
}
}
for(int i=1;i<=n;i++)
{
bit.add(a[i]+1,1);
bit2.add(a[i]+1,i);
pf[i]=bit.qry(a[i]);
pf2[i]=bit2.qry(a[i]);
}
for(int i=1;i<=n;i++)
{
blk.add(a[i],1);
blk2.add(a[i],i);
for(auto [l,r,j]:qry1[i])
{
for(int k=l;k<=r;k++)
{
ans1[j]+=blk.qry(a[k]-1)-pf[k];
ans2[j]+=blk2.qry(a[k]-1)-pf2[k];
}
}
}
mset(bit.tree,0);
blk.clr();
for(int i=n;i;i--)
{
bit.add(a[i],1);
sf[i]=n-i+1-bit.qry(a[i]);
}
for(int i=n;i;i--)
{
blk.add(a[i],1);
for(auto [l,r,j]:qry2[i])
{
for(int k=l;k<=r;k++)
{
int t=n-i+1-blk.qry(a[k])-sf[k];
ans1[j]+=t;
ans2[j]+=t*k;
}
}
}
L=1,R=0;
m=0;
int c1=0,c2=0;
for(auto [l,r,i,ad]:qry)
{
if(l<L)
{
m++;
c1+=ans1[m];
c2+=ans2[m];
L=l;
}
if(R<r)
{
m++;
c1+=ans1[m];
c2+=ans2[m];
R=r;
}
if(L<l)
{
m++;
c1-=ans1[m];
c2-=ans2[m];
L=l;
}
if(r<R)
{
m++;
c1-=ans1[m];
c2-=ans2[m];
R=r;
}
ans[i]+=((r+1)*c1-c2)*ad;
}
for(int i=1;i<=Q;i++)
printf("%lld\n",ans[i]);
return 0;
}