莫队两个区间

链接: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

输入

复制
5 1
2 2 2 2 2
1 5 1 3 2

输出

复制
5
3
15

说明

对于所有数据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);
    }
}

 

 
posted @ 2021-01-24 13:35  lipu123  阅读(48)  评论(0编辑  收藏  举报