您的位置:首页 > 其它

hdu 3874【Necklace】

2013-03-24 13:14 113 查看
看了别人的线段树的题解才知道思路的,然后用树状数组写出来

解决方案是:将询问的区间先存下来,然后按right边界排序

然后将排序后的询问按从左到右的顺序解决,从起始元素开始到right,依次插入到树状数组中去,如果之前有相同的数已经插入过(用hash判断即可),就从树状数组中(从先前那个相同的数的位置开始)删除加的那个数(即在树状数组中插入那个数的负值),然后再插入当前的这个数(从当前的数的这个位置)

然后就询问,将结果存在ans数组里面

提示:我用g++编译的,那个__int64_t要改成__int64后提交,后面的那个输出(打印结果的地方)要改成"%I64d"输出才行。。。一直WA,就是因为我用的long long

代码如下:

#include <cstdio>
#include <algorithm>
#include <cstring>

typedef __int64_t ll;
const int maxN = 50000 + 10;
const int maxM = 200000 + 10;

int balls[maxN];
ll ans[maxM];
int hash[1000010];

struct node
{
int l,r;
int id;
node(){}
node(int left,int right,int curl)
{
l = left;
r = right;
id = curl;
}
}asks[maxM];

ll tree[maxN];

void update(int curl,int value,int n)
{
while(curl <= n)
{
tree[curl] += value;
curl += (curl & (-curl));
}
}

ll getSum(int curl)
{
ll sum = 0;
while(curl > 0)
{
sum += tree[curl];
curl -= (curl & (-curl));
}

return sum;
}

bool cmp(const node a,const node b)
{
if(a.r == b.r)
{
return a.l < b.l;
}
return a.r < b.r;
}

int main()
{
int cases;
int n,m;

scanf("%d",&cases);

while(cases --)
{
scanf("%d",&n);
for(int i = 1;i <= n;i ++)
{
scanf("%d",&balls[i]);
}

memset(hash,0,sizeof(hash));
//memset(ans,0,sizeof(ans));
memset(tree,0,sizeof(tree));
scanf("%d",&m);
int a,b;
for(int i = 1;i <= m;i ++)
{
scanf("%d%d",&a,&b);
if(a > b)
{
int t = a;
a = b;
b = t;
}
asks[i] = node(a,b,i);
}

std::sort(asks+1,asks+m+1,cmp);

int run = 1;
for(int i = 1;i <= m;i ++)
{
while(run <= asks[i].r)
{
if(hash[balls[run]])
{
update(hash[balls[run]],-balls[run],n);
}

update(run,balls[run],n);
hash[balls[run]] = run;

run ++;
}

ans[asks[i].id] = getSum(asks[i].r) - getSum(asks[i].l - 1);
}

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

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: