[hdu 4417]树状数组+离散化+离线处理

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4417

把数字离散化,一个查询拆成两个查询,每次查询一个前缀的和。主要问题是这个数组是静态的,如果带修改操作就不能离线了。

//http://acm.hdu.edu.cn/showproblem.php?pid=4417
#include<bits/stdc++.h>
using namespace std;

const int maxn=100005;
int tree[maxn];
int N;

int lowbit(int x)
{
    return x&-x;
}

void init(int n)
{
    N=n;
    for (int i=1;i<=n;i++) tree[i]=0;
}

void add(int k,int x)
{
    while (k<=N)
    {
        tree[k]+=x;
        k+=lowbit(k);
    }
}

int sum(int k)
{
    int res=0;
    while (k)
    {
        res+=tree[k];
        k-=lowbit(k);
    }
    return res;
}

vector<int> ls;
int a[maxn];

struct Query
{
    int id;
    int sgn;
    int p,j;
    int res;
    bool operator < (const Query & q) const
    {
        return p<q.p;
    }
}query[maxn*2];

int ans[maxn];

int main()
{
    int t;
    scanf("%d",&t);
    for (int cas=1;cas<=t;cas++)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        for (int i=1;i<=n;i++) scanf("%d",&a[i]);
        ls.clear();
        for (int i=1;i<=n;i++) ls.push_back(a[i]);
        sort(ls.begin(),ls.end());
        ls.erase(unique(ls.begin(),ls.end()),ls.end());
        for (int i=0;i<m;i++)
        {
            int l,r,h;
            scanf("%d%d%d",&l,&r,&h);
            l++;
            r++;
            int j=upper_bound(ls.begin(),ls.end(),h)-ls.begin();
            query[i*2].id=i;
            query[i*2].p=l-1;
            query[i*2].j=j;
            query[i*2].sgn=-1;
            query[i*2+1].id=i;
            query[i*2+1].p=r;
            query[i*2+1].j=j;
            query[i*2+1].sgn=1;
        }
        sort(query,query+m*2);
        init(ls.size());
        int now=0;
        for (int i=0;i<=n;i++)
        {
            if (i)
            {
                int j=lower_bound(ls.begin(),ls.end(),a[i])-ls.begin()+1;
                add(j,1);
            }
            while (now<m*2 && query[now].p==i)
            {
                query[now].res=sum(query[now].j);
                now++;
            }
        }
        memset(ans,0,sizeof(ans));
        for (int i=0;i<m*2;i++) ans[query[i].id]+=query[i].res*query[i].sgn;
        printf("Case %d:\n",cas);
        for (int i=0;i<m;i++) printf("%d\n",ans[i]);
    }
    return 0;
}

 

posted @ 2017-09-28 17:03  ACMsong  阅读(240)  评论(0编辑  收藏  举报