AT_abc106_d [ABC106D] AtCoder Express 2 题解
分析
对于求满足
很显然,我们是无法二分
对于求区间答案,不难想到莫队。对于指针的每次移动,我们可用一棵树状数组更新数量。而在指针移动完之后,该询问的答案就可以直接用树状数组求得
代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define PII pair<int,int>
#define x first
#define y second
#define re register
const int N=1e6+10,M=1e4+10;
int n,m,q;
struct node{
int l,r,cnt;
}c[N],c1[N];
int cidx;
struct node2{
int p,q;
}Q[N];
struct node3{
int l,r,id,k;
}Q2[N];
int ANS[N],idx,len;
int tr[M];//树状数组
inline bool cmp(node a,node b){
return ((a.l!=b.l)?(a.l<b.l):(a.r<b.r));
}
inline bool cmp2(node3 a,node3 b){
if(a.l/len!=b.l/len) return a.l<b.l;
if((a.l/len)&1) return a.r<b.r;
return a.r>b.r;
}
inline int find1(int l,int r,int x){
int ans=0;
while(l<=r){
int mid=l+r>>1;
if(c1[mid].l>=x) ans=mid,r=mid-1;
else l=mid+1;
}
return ans;
}
inline int find2(int l,int r,int x){
int ans=0;
while(l<=r){
int mid=l+r>>1;
if(c1[mid].l<=x) ans=mid,l=mid+1;
else r=mid-1;
}
return ans;
}
inline void insert(int x,int y){
while(x<=n+10) tr[x]+=y,x+=x&(-x);
}
inline int query(int x){
int ans=0;
while(x) ans+=tr[x],x-=x&(-x);
return ans;
}
inline void read(){
scanf("%lld%lld%lld",&n,&m,&q);
for(re int i=1;i<=m;++i)
scanf("%lld%lld",&c[i].l,&c[i].r);
for(re int i=1;i<=q;++i)
scanf("%lld%lld",&Q[i].p,&Q[i].q);
return ;
}
inline void solve(){
sort(c+1,c+m+1,cmp);
int last=1;
for(re int i=2;i<=m+1;++i)//合并相同项
if(c[i].l!=c[i-1].l||c[i].r!=c[i-1].r) c1[++cidx]={c[i-1].l,c[i-1].r,last},last=1;
else ++last;
for(re int i=1;i<=q;++i){//二分查找i的区间
int where=find1(1,cidx,Q[i].p);
int where2=find2(where,cidx,Q[i].q);
if(where>where2||where<1||where2<1) ANS[i]=0;
else Q2[++idx]={where,where2,i,Q[i].q};
}
len=sqrt(idx);
sort(Q2+1,Q2+idx+1,cmp2);
int l=1,r=0;
for(re int i=1;i<=idx;++i){//莫队
while(l>Q2[i].l) --l,insert(c1[l].r,c1[l].cnt);
while(r<Q2[i].r) ++r,insert(c1[r].r,c1[r].cnt);
while(l<Q2[i].l) insert(c1[l].r,-c1[l].cnt),++l;
while(r>Q2[i].r) insert(c1[r].r,-c1[r].cnt),--r;
ANS[Q2[i].id]=query(Q2[i].k);
}
for(re int i=1;i<=q;++i)
printf("%lld\n",ANS[i]);
return ;
}
signed main(){
read(),solve();return 0;
}