您的位置:首页 > 其它

HDU 3874 Necklace

2012-08-02 20:35 323 查看
http://acm.hdu.edu.cn/showproblem.php?pid=3874

今天和涂涂新学的离线算法,太牛了

大概就是先接收所有数据,然后按查询右边界排序,从左往右更新,遇到之前加过的数就删掉,因为按右边界排序,所以查询区间不断右移,删掉不会出错

View Code

#include <iostream>
#include <algorithm>
#include <map>
using namespace std ;
const int maxn=50001 ;
typedef __int64 LL ;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
map <int,int> hash ;
struct node{
int l,r,id ;
}kk[maxn<<2] ;
int a[maxn] ;
LL sum[maxn<<2] ;
LL ans[maxn<<2] ;
void pushup(int rt)
{
sum[rt]=sum[rt<<1]+sum[rt<<1|1] ;
}
void update(int p,int add,int l,int r,int rt)
{
if(l==r)
{
sum[rt]+=add ;
return ;
}
int m=(l+r)>>1 ;
if(p<=m)
update(p,add,lson) ;
else
update(p,add,rson) ;
pushup(rt) ;
}
LL query(int L,int R,int l,int r,int rt)
{
if(L<=l && R>=r)
return sum[rt] ;
int m=(l+r)>>1 ;
LL ret=0 ;
if(L<=m)
ret+=query(L,R,lson) ;
if(R>m)
ret+=query(L,R,rson) ;
return ret ;
}
bool cmp(node a,node b)
{
return a.r<b.r ;
}
int main()
{
int t ;
scanf("%d",&t) ;
while(t--)
{
int n ;
scanf("%d",&n) ;
for(int i=1;i<=n;i++)
scanf("%d",&a[i]) ;
int m ;
scanf("%d",&m) ;
for(int i=1;i<=m;i++)
{
scanf("%d%d",&kk[i].l,&kk[i].r) ;
kk[i].id=i ;
}
sort(kk+1,kk+m+1,cmp) ;
hash.clear() ;
memset(sum,0,sizeof(sum)) ;
int r=1 ;
for(int i=1;i<=m;i++)
{
while(r<=kk[i].r)
{
if(hash[a[r]])
update(hash[a[r]],-a[r],1,n,1) ;
update(r,a[r],1,n,1) ;
hash[a[r]]=r ;
r++ ;
}
ans[kk[i].id]=query(kk[i].l,kk[i].r,1,n,1) ;
}
for(int i=1;i<=m;i++)
printf("%I64d\n",ans[i]) ;
}
return 0 ;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: