莫队两个区间
链接:https://ac.nowcoder.com/acm/contest/917/H
来源:牛客网
题目描述
输入描述:
第一行一个n,m 接下来一行n个数表示a[i] 接下来m行,每行l,r,l1,r1,x,表示求get(l,r,x)*get(l1,r1,x)
输出描述:
3×m行,先输出get(l,r,x),再输出get(l1,r1,x),再输出get(l,r,x)*get(l1,r1,x)
示例1
说明
对于所有数据1<=n,m<=105;1<=l,r,l1,r1<=1051<=n,m<=10^5 ;1<=l,r,l1,r1<=10^5
提示:20180623不是质数
对于这个题就是分开成两部分,通过下标联系,在排序
就是这个操作
#include<iostream> #include<algorithm> using namespace std; typedef long long ll; const int maxn=1e6+100; int a[maxn]; int belong[maxn]; ll ans[maxn]; ll vis[maxn]; const int mod=20180623; int n,m,block; struct node{ int l,r; ll x; int id; }q[maxn]; bool cmp(node x,node y){ if(belong[x.l]!=belong[y.l]){ return belong[x.l]<belong[y.l]; } else{ if(belong[x.l]&1){ return x.r<y.r; } else{ return x.r>y.r; } } } void add(int pos){ vis[a[pos]]++; } void remove(int pos){ vis[a[pos]]--; } int main(){ cin>>n>>m; block=sqrt(n); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); belong[i]=(i-1)/block+1; } int l,r,l1,r1,x; for(int i=1;i<=m;i++){ scanf("%d%d%d%d%d",&l,&r,&l1,&r1,&x); if (l>r) swap(l,r); if (l1>r1) swap(l1,r1); q[i].l=l,q[i].r=r; q[i].id=i; q[i].x=x; q[i+m].l=l1,q[i+m].r=r1; q[i+m].id=i+m; q[i+m].x=x; } sort(q+1,q+2*m+1,cmp); l=1,r=0; for(int i=1;i<=2*m;i++){ int ql=q[i].l,qr=q[i].r; while(l<ql){ remove(l++); } while(l>ql){ add(--l); } while(r>qr){ remove(r--); } while(r<qr){ add(++r); } ans[q[i].id]=vis[q[i].x]; } for(int i=1;i<=m;i++){ printf("%lld\n%lld\n%lld\n",ans[i]%mod,ans[i+m]%mod,(ans[i]%mod*ans[i+m]%mod)%mod); } }