您的位置:首页 > 其它

HDU 3874 离线段树

2015-10-23 13:24 260 查看
在所有数字的统计范围,,对于重复统计只有一次

离线段树算法

排序终点坐标。然后再扫,反复交锋。把之前插入树行被删除

#include "stdio.h"
#include "string.h"
#include "algorithm"
using namespace std;

struct node
{
int l,r;
__int64 sum;
}data[200010];

struct Mark
{
int l,r,id;
}mark[200010];

int hash[1000001];
__int64 a[50010],ans[200010];
bool cmp(Mark a,Mark b)
{
return a.r<b.r;
}

void build (int l,int r,int k)
{
int mid;
data[k].l=l;
data[k].r=r;
data[k].sum=0;

if (l==r) return ;
mid=(l+r)/2;

build(l,mid,k*2);
build(mid+1,r,k*2+1);
}

void updata(int n,int k,int op)
{
int mid;
if (data[k].l==n && data[k].r==n)
{
data[k].sum+=op;
return ;
}

mid=(data[k].l+data[k].r)/2;
if (n<=mid) updata(n,k*2,op);
else updata(n,k*2+1,op);

data[k].sum=data[k*2].sum+data[k*2+1].sum;
}

__int64 query(int l,int r,int k)
{
int mid;
if (data[k].l==l && data[k].r==r)
return data[k].sum;
mid=(data[k].l+data[k].r)/2;

if (r<=mid) return query(l,r,k*2);
else
if (l>mid) return query(l,r,k*2+1);
else
return query(l,mid,k*2)+query(mid+1,r,k*2+1);
}

int main()
{
int Case,i,n,m,now;

scanf("%d",&Case);
while (Case--)
{
scanf("%d",&n);
for (i=1;i<=n;i++)
scanf("%I64d",&a[i]);
scanf("%d",&m);
for (i=0;i<m;i++)
{
scanf("%d%d",&mark[i].l,&mark[i].r);
mark[i].id=i;
}
sort(mark,mark+m,cmp);

build(1,50000,1);
memset(hash,0,sizeof(hash));
now=1;
for (i=0;i<m;i++)
{
while (now<=mark[i].r)
{
if (hash[a[now]]!=0)
updata(hash[a[now]],1,-a[now]);
hash[a[now]]=now;
updata(now,1,a[now]);
now++;
}
ans[mark[i].id]=query(mark[i].l,mark[i].r,1);
}
for (i=0;i<m;i++)
printf("%I64d\n",ans[i]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: