hdu 3874 Necklace

http://acm.hdu.edu.cn/showproblem.php?pid=3874

这题题目是好题呀!可以我想不出来,看了网上的题解才明白!

当时我想的是枚举从1 到 当前 r 区间中只出现一次的和,但是对于 询问 【l ,r】就 如果某个数在 只在[ 1 , L-1]  或者 [ l , r ] 区间出现答案都正确,但是对于 有些数 在两个区间都出现的话,一减的话相当于没有出现,答案就不对了…… 看了网上的解题办法,是这样的话,如果当前的数之前出现的话,那么把之前的位置处减去,然后再当前位置插入……


离线查询


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


using namespace std;
#define lowbit(x) x&(-x)
const int maxn=500100;
typedef long long ll;

ll d[maxn],ans[maxn];
int n,last[1000010],a[maxn];

struct Node
{
    int l,r,id;
}node[200010];

int cmp(Node a,Node b)
{
    if(a.r!=b.r) return  a.r < b.r;
    return a.l < b.l;
}
void add(int p,int val)
{
    for(int i=p;i<=n;i+=lowbit(i))
      d[i]+=val;
}
ll query(int p)
{
    ll sum=0;
    for(int i=p;i>=1;i-=lowbit(i))
      sum+=d[i];
    return sum;
}
int main()
{
    int m,ca;
    scanf("%d",&ca);
    while(ca--)
    {
        scanf("%d",&n);
        memset(d,0,sizeof(d));
        memset(last,-1,sizeof(last));
        for(int i=1;i<=n;i++)
          scanf("%d",&a[i]);
        scanf("%d",&m);
        for(int i=0;i<m;i++)
          scanf("%d %d",&node[i].l,&node[i].r),node[i].id=i;
        sort(node,node+m,cmp);
        int r=1;
        for(int i=0;i<m;i++)
        {
            while(r<=node[i].r)
            {
                if(last[a[r]]!=-1) add(last[a[r]],-a[r]);
                last[a[r]]=r;
                add(r,a[r]);
                r++;
            }
            ans[node[i].id]=query(node[i].r)-query(node[i].l-1);
        }
        for(int i=0;i<m;i++)
          printf("%I64d\n",ans[i]);
    }
    return 0;
}



你可能感兴趣的:(hdu 3874 Necklace)