ASC 41 Problem D. Data Mining

21 篇文章 0 订阅


ASC 41

题意:给n个数,q个查询,每次询问序列中以第L个数为开头的后缀中,第x个数在这个后缀中是第几个出现的。


离线查询。

将查询按L从小到大排序,预处理每个数上一次出现的位置。

每次插入上一次出现位置在L之前的数,显然会将所有L之前的数都加入,然后查询这个数在后缀中第一次出现的位置(设为p)之前的前缀和。

由于L之前所有数都被加入,且[L,p]之间的所有数有且仅有被插入一次,所以就能得到了这个询问的答案。



#include <bits/stdc++.h>
using namespace std;
const int MAXN=200005;
int a[MAXN], ans[MAXN], disc[MAXN];
int last[MAXN], bit[MAXN];
vector<int> pos[MAXN];
pair<int, int> pre[MAXN];
struct query{
    int pos, p, idx, num;
    bool operator < (const query& Rhs) const{
        return pos < Rhs.pos;
    }
}q[MAXN];
void add(int x, int v){
    while(x<MAXN){
        bit[x]+=v;
        x+=x&(-x);
    }
}
int query(int x){
    int ret=0;
    while(x>0){
        ret+=bit[x];
        x-=x&(-x);
    }
    return ret;
}
int main(){
    freopen("data.in","r",stdin);
    freopen("data.out","w",stdout);
    int n; cin>>n;
    for(int i=1; i<=n; i++){
        scanf("%d",&a[i]);
        disc[i]=a[i];
    }
    sort(disc+1,disc+n+1);
    int tot = unique(disc+1,disc+n+1)-disc;
    for(int i=1; i<=n; i++){
        a[i]=lower_bound(disc+1,disc+tot,a[i])-disc;
        pos[a[i]].push_back(i);
    }
    int m; cin>>m;
    for(int i=1; i<=m; i++){
        scanf("%d%d",&q[i].pos,&q[i].p);
        int x=a[q[i].pos+q[i].p-1];
        q[i].idx=i; q[i].num=*lower_bound(pos[x].begin(),pos[x].end(),q[i].pos);
    }
    sort(q+1,q+m+1);
    memset(last,-1,sizeof last);
    for(int i=1; i<=n; i++){
        pre[i]=make_pair(last[a[i]],i);
        last[a[i]]=i;
    }
    sort(pre+1,pre+n+1);
    for(int i=1, j=1; i<=m; i++){
        for(; j<=n&&pre[j].first<q[i].pos; j++){
            add(pre[j].second,1);
        }
        ans[q[i].idx]=query(q[i].num)-q[i].pos+1;
    }
    for(int i=1; i<=m; i++){
        printf("%d\n",ans[i]);
    }
    return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值