您的位置:首页 > 其它

HDU 3874__Necklace

2017-07-11 18:59 381 查看
题目描述:

Mery has a beautiful necklace. The necklace is made up of N magic balls. Each ball has a beautiful value. The balls with the same beautiful value look the same, so if two or more balls have the
same beautiful value, we just count it once. We define the beautiful value of some interval x,yx,y as
F(x,y). F(x,y) is calculated as the sum of the beautiful value from the xth ball to the yth ball and the same value is ONLY COUNTED ONCE. For example, if the necklace is 1 1 1 2 3 1, we have F(1,3)=1, F(2,4)=3, F(2,6)=6. 

Now Mery thinks the necklace is too long. She plans to take some continuous part of the necklace to build a new one. She wants to know each of the beautiful value of M continuous parts of the necklace.
She will give you M intervals L,RL,R (1&l
b345
t;=L<=R<=N)
and you must tell her F(L,R) of them

题意就是给你长度为N的序列并有M次询问,没次询问求区间[L,R]的和,重复的数只计算一次;

其中1 <=N <=50000,1 <=M <=200000,1<=L<=R<=N,然后序列中的任意数不会大于1e6;

样例:

input:

2
6
1 2 3 4 3 5
3
1 2
3 5
2 6
6
1 1 1 2 3 5
3
1 1
2 4
3 5

output:

3
7
14
1
3
6


这题比较麻烦一点的是重复的数只能计算一次,我的做法是现将所有的询问保存起来,然后按R从小到大L从小到大的顺序的排序,这样可以保证我查询区间的有序性,然后用一个标记数组来记录每个数出现过的位置,如果我在查询区间时发现这个数已经被标记过就说明这个数已经在这个区间内算过和,那么我们就将这个数从该位置从树状数组中删去,并且不计算这个数,如果这个数没有被标记过,我就计算这个数,并且更新这个数存在的位置,保证标记数组中储存了每个数出现的最后的位置,这样我按顺序扫描区间时就可以保证计算和时不会重复计算相同的数。

AC代码:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<string>
#include<stack>
#include<queue>
#include<algorithm>
using namespace std;
const int MAXM=100010;
const int INF=1000010;
struct question
{
int l,r;
int id;
};

int n;
int a[5*MAXM];
struct question q[4*MAXM];
int vis[INF];
long long bit[MAXM*10];
long long ans[4*MAXM];

bool cmp(question q1,question q2)
{
if (q1.r==q2.r) return q1.l<q2.l;
return q1.r<q2.r;
}
int lowbit(int x)
{
return x&(-x);
}
void add(int x,int val)
{
while(x<10*MAXM)
{
bit[x]+=val;
x+=lowbit(x);
}
}
long long sum(int x)
{
long long t=0;
while(x>0)
{
t+=bit[x];
x-=lowbit(x);
}
return t;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
scanf("%d",&a[i]);
int Q;
scanf("%d",&Q);
for (int i=1;i<=Q;i++)
{
int l,r;
scanf("%d%d",&l,&r);
q[i].l=l;
q[i].r=r;
q[i].id=i;
}
sort(q+1,q+1+Q,cmp);
memset(vis,-1,sizeof(vis));
memset(bit,0,sizeof(bit));
memset(ans,0,sizeof(ans));
int ll=1;
for (int i=1;i<=Q;i++)
{
while(ll<=q[i].r)
{
//printf("------%d\n",vis[a[ll]]);
if (vis[a[ll]]!=-1)
{
add(vis[a[ll]],-a[ll]);
}
add(ll,a[ll]);
vis[a[ll]]=ll;
ll++;
}
ans[q[i].id]=sum(q[i].r)-sum(q[i].l-1);
//printf("--%d--%d\n",sum(q[i].r),sum(q[i].l-1));
}
for (int i=1;i<=Q;i++)
printf("%I64d\n",ans[i]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: