D-query SPOJ Fenwick tree offline +

D-query SPOJ Fenwick tree offline +

The meaning of problems

There are a bunch of positive numbers, find how many different numbers have a certain interval

Problem-solving ideas

Explain, Fenwick tree to start all zeros.

First of all, we are able to save all sections need to query, from small to large and then sorted according to the right point. Followed by processing this range of answers, carefully think about the answer back section is not affected.

How to deal with it in the answer section?

We appear in numerical order, plus an array to a tree, if there is a previous figure, you need to position Fenwick tree appears in the figure last minus one, so you can guarantee within a certain range, each number in the tree only has a corresponding array 1, when the process reaches the right end position to the digital interrogation point a, can be in order to ask about this section 1 has several, is the number of different sections in this figure.

It should appear before the digital mark over whether, and therefore opened a vis the array, but the scope of the title number that appears too large to enter the number of digits is not a lot, it can be discrete, re-mapped to a small interval. Of course, you can also use the map.

+ Summing point operation section can be used just to tree array.

Here is the code to achieve, notes can be more clear.

Code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
using namespace std;
typedef long long ll;
const int maxn=3e4+7;
const int maxq=2e5+7;
struct query{
    int L, R, id;
    bool friend operator <(query a, query b)
    {
        return a.R < b.R;
    }
}q[maxq];
int num[maxn]; //存储那一串数字
int bak[maxn]; //备份数字,用来进行离散化
int sum[maxn]; //树状数组
int pre[maxn]; //记录数字之前出现的位置
int vis[maxn]; //标记数字是否出现过
int ans[maxq]; //离线处理,需要记录答案,之后一并输出
int n, m, cnt; //n数字的个数,m个询问,cnt是映射后的范围
void up(int id, int x)
{
    while(id<=n)
    {
        sum[id]+=x;
        id += id&(-id);
    }
} 

ll getsum(int id)
{
    ll ret=0;
    while(id>0)
    {
        ret+=sum[id];
        id -= id&(-id);
    }   
    return ret;
} 
int getid(int num) //求映射后的编码
{
    return lower_bound(bak, bak+cnt, num)-bak+1;
}
int main()
{
    while(scanf("%d", &n)!=EOF)
    {
        for(int i=1;i<=n; i++) //初始化
        {
            sum[i]=0;
            vis[i]=0;
        }
        for(int i=1; i<=n; i++) //读入数据+备份。
        {
            scanf("%d", &num[i]);
            bak[i-1]=num[i];//从0开始便于后面初始化
        }   
        scanf("%d", &m);
        for(int i=1; i<=m; i++)//读入查询
        {
            scanf("%d%d", &q[i].L, &q[i].R);
            q[i].id=i;
        }
        sort(q+1, q+m+1);//排序
        sort(bak, bak+n);//离散化先排序
        cnt=unique(bak, bak+n)-bak;//去重后的个数
        int j=1; 
        for(int i=1; i<=m; i++)
        {
            while(j <= q[i].R && j<=n)
            {
                int tmp=getid(num[j]); //获取编号
                if(vis[tmp]!=0)
                {
                    up(pre[tmp], -1);
                    pre[tmp]=j;
                    up(j, 1);
                    j++;
                }
                else {
                    pre[tmp]=j;
                    vis[tmp]=1;
                    up(j, 1);
                    j++;
                }
            }
            ans[q[i].id]=getsum(q[i].R)-getsum(q[i].L-1);
        }
        for(int i=1; i<=m; i++)
        {
            printf("%d\n", ans[i]);
        }
    }   
    return 0;
} 

Guess you like

Origin www.cnblogs.com/alking1001/p/11314424.html