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:
output:
这题比较麻烦一点的是重复的数只能计算一次,我的做法是现将所有的询问保存起来,然后按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;
}
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;
}
相关文章推荐
- HDU 3874 Necklace(离线算法+树状数组)
- HDU 3874 Necklace 树状数组
- hdu 3874 Necklace(离线操作+树状数组或线段树)
- HDU - 3874 Necklace解题报告(树状数组+哈希表)
- HDU 3333&&HDU-3874 Necklace 离线树状数组
- HDU 3874 Necklace 树状数组的应用
- hdu_3874 Necklace
- hdu 3874 Necklace
- hdu 3874 Necklace(树状数组的灵活应用)
- HDU 3874 Necklace
- HDU 3874 Necklace 树状数组 + 离线处理
- HDU-3874 Necklace 线段树+离线
- HDU 3874 Necklace 树状数组
- hdu 3874 Necklace(线段树)
- hdu 3333 Turing Tree & hdu 3874 Necklace (成段更新)
- 【HDU - 3874 Necklace】 线段树
- hdu 3874 Necklace 求数组任意区间和(相同元素只算一次) 树状数组+离线算法
- HDU-3874 Necklace 树状数组+离线处理
- HDU 3874 Necklace (树状数组 | 线段树 的离线处理)
- HDU 3874 Necklace 莫队算法