心如止水
Je n'ai pas le temps
posts - 400,comments - 130,trackbacks - 0
树状数组的应用。
采用离线算法:先按询问的右端点排序,然后依次把数字插入到树状数组里面,pos[i]记录数字i上一次在数组里面出现的位置,如果i已经出现过,删除之前的,添加到当前的位置。遇到可以处理的询问则处理,同时存储结果。
以下是我的代码:
#include<iostream>
#include
<algorithm>
#include
<cstdio>
#include
<cstring>
#define lowbit(x) ((x)&(-(x)))
using namespace std;
const int kMaxn(50007);
const int kMaxm(200007);
const int kMaxv(1000007);

struct Interval
{
    
int a,b;
    
int id;
};
bool operator<(const Interval &a,const Interval &b)
{
    
return (a.b<b.b);
}

int n,m,r[kMaxn];
Interval query[kMaxm];
long long bit[kMaxn],ans[kMaxm];
int pos[kMaxv];

void Add(int x,int delta)
{
    
for(int i=x;i<=n;i+=lowbit(i))
        bit[i]
+=delta;
}

long long Sum(int x)
{
    
long long re(0);
    
for(int i=x;i>0;i-=lowbit(i))
        re
+=bit[i];
    
return re;
}

int main()
{
    
//freopen("data.in","r",stdin);

    
int T;
    scanf(
"%d",&T);
    
while(T--)
    {
        scanf(
"%d",&n);
        
for(int i=1;i<=n;i++)
            scanf(
"%d",&r[i]);
        scanf(
"%d",&m);
        
for(int i=1;i<=m;i++)
        {
            scanf(
"%d%d",&query[i].a,&query[i].b);
            query[i].id
=i;
        }

        
//  Input

        sort(query
+1,query+m+1);
        memset(bit,
0,sizeof(bit));
        memset(pos,
-1,sizeof(pos));

        
for(int i=1,j=1;i<=&& j<=m;i++)
        {
            Add(i,r[i]);
            
if(pos[r[i]]!=-1)
                Add(pos[r[i]],
-r[i]);
            pos[r[i]]
=i;

            
while(i==query[j].b)
            {
                ans[query[j].id]
=Sum(query[j].b)-Sum(query[j].a-1);
                j
++;
            }
        }

        
for(int i=1;i<=m;i++)
            printf(
"%I64d\n",ans[i]);
    }

    
return 0;
}
posted on 2011-08-01 11:56 lee1r 阅读(532) 评论(0)  编辑 收藏 引用 所属分类: 题目分类:数据结构

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理