hdu 3333 Turing Tree(图灵树,线段树,离散化)
2014-08-14 15:59
232 查看
题目大意:
求区间内不同的数字的和。这题用一般性的线段树写的时候没法处理相同的数字。
解题思路:
首先离散化,因为数字太大。
然后读入所有的询问区间,以右端为基准进行排序。这样能保证如果某个数字前面出现过,在原来位置删去,在新位置插入不会影响结果。因为越往后面,区间的右端越大。
然后线段树查询区间和的时候不变。
下面是代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 120009
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define LL __int64
LL sum[maxn];
void build(int l,int r,int rt)
{
sum[rt]=0;
if(l==r)return ;
int m =(l+r)>>1;
build(lson);
build(rson);
}
void pushup(int rt)
{
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void update(int l,int r,int rt,int p,int flag,int num)
{
if(l==r)
{
sum[rt]+=flag*num;
return ;
}
int m = (l+r)>>1;
if(m>=p)update(lson,p,flag,num);
else update(rson,p,flag,num);
pushup(rt);
}
LL query(int l,int r,int rt,int L,int R)
{
if(l>=L&&r<=R)return sum[rt];
int m =(l+r)>>1;
LL ans =0;
if(m>=L) ans += query(lson,L,R);
if(m<R) ans += query(rson,L,R);
return ans ;
}
struct node
{
int l,r,id;
} nod[100009];
bool cmp(node a,node b)
{
return a.r<b.r;
}
struct Tem
{
int a,id;
} tem[30009];
bool cmp1(Tem x,Tem y)
{
return x.a<y.a;
}
bool cmp2(Tem x,Tem y)
{
return x.id<y.id;
}
int main()
{
int n,m,i,j,T;
LL an[100009];
int a1[30009];
int vis[30009];
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(i=0; i<n; i++)
{
scanf("%d",&tem[i].a);
tem[i].id=i+1;
}
sort(tem,tem+n,cmp1);
a1[tem[0].id]=1;
for(i=1; i<n; i++)
{
a1[tem[i].id]=a1[tem[i-1].id];
if(tem[i].a!=tem[i-1].a)a1[tem[i].id]++;
}
sort(tem,tem+n,cmp2);
scanf("%d",&m);
for(i=0; i<m; i++)
{
scanf("%d%d",&nod[i].l,&nod[i].r);
nod[i].id=i;
}
sort(nod,nod+m,cmp);
j=1;
memset(vis,0,sizeof(vis));
build(1,n,1);
for(i=0; i<m; i++)
{
while(j<=nod[i].r)
{
if(vis[a1[j]]!=0)
update(1,n,1,vis[a1[j]],-1,tem[j-1].a);
update(1,n,1,j,1,tem[j-1].a);
vis[a1[j]]=j;
j++;
}
an[nod[i].id] =query(1,n,1,nod[i].l,nod[i].r);
}
for(i=0; i<m; i++)
printf("%I64d\n",an[i]);
}
return 0;
}
求区间内不同的数字的和。这题用一般性的线段树写的时候没法处理相同的数字。
解题思路:
首先离散化,因为数字太大。
然后读入所有的询问区间,以右端为基准进行排序。这样能保证如果某个数字前面出现过,在原来位置删去,在新位置插入不会影响结果。因为越往后面,区间的右端越大。
然后线段树查询区间和的时候不变。
下面是代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 120009
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define LL __int64
LL sum[maxn];
void build(int l,int r,int rt)
{
sum[rt]=0;
if(l==r)return ;
int m =(l+r)>>1;
build(lson);
build(rson);
}
void pushup(int rt)
{
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void update(int l,int r,int rt,int p,int flag,int num)
{
if(l==r)
{
sum[rt]+=flag*num;
return ;
}
int m = (l+r)>>1;
if(m>=p)update(lson,p,flag,num);
else update(rson,p,flag,num);
pushup(rt);
}
LL query(int l,int r,int rt,int L,int R)
{
if(l>=L&&r<=R)return sum[rt];
int m =(l+r)>>1;
LL ans =0;
if(m>=L) ans += query(lson,L,R);
if(m<R) ans += query(rson,L,R);
return ans ;
}
struct node
{
int l,r,id;
} nod[100009];
bool cmp(node a,node b)
{
return a.r<b.r;
}
struct Tem
{
int a,id;
} tem[30009];
bool cmp1(Tem x,Tem y)
{
return x.a<y.a;
}
bool cmp2(Tem x,Tem y)
{
return x.id<y.id;
}
int main()
{
int n,m,i,j,T;
LL an[100009];
int a1[30009];
int vis[30009];
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(i=0; i<n; i++)
{
scanf("%d",&tem[i].a);
tem[i].id=i+1;
}
sort(tem,tem+n,cmp1);
a1[tem[0].id]=1;
for(i=1; i<n; i++)
{
a1[tem[i].id]=a1[tem[i-1].id];
if(tem[i].a!=tem[i-1].a)a1[tem[i].id]++;
}
sort(tem,tem+n,cmp2);
scanf("%d",&m);
for(i=0; i<m; i++)
{
scanf("%d%d",&nod[i].l,&nod[i].r);
nod[i].id=i;
}
sort(nod,nod+m,cmp);
j=1;
memset(vis,0,sizeof(vis));
build(1,n,1);
for(i=0; i<m; i++)
{
while(j<=nod[i].r)
{
if(vis[a1[j]]!=0)
update(1,n,1,vis[a1[j]],-1,tem[j-1].a);
update(1,n,1,j,1,tem[j-1].a);
vis[a1[j]]=j;
j++;
}
an[nod[i].id] =query(1,n,1,nod[i].l,nod[i].r);
}
for(i=0; i<m; i++)
printf("%I64d\n",an[i]);
}
return 0;
}
相关文章推荐
- hdu 3333 Turing Tree(线段树+离散化)
- hdu 3333 Turing Tree(线段树+离散化)
- hdu 3333 Turing Tree(线段树求区间内不同值之和+离线处理)
- SPOJ D-query && HDU 3333 Turing Tree (线段树 && 区间不相同数个数or和 && 离线处理)
- HDU 3333 Turing Tree(线段树)
- HDU 3333 Turing Tree(树状数组+离线处理+离散化)
- hdu 3333 Turing Tree 线段树 离线查询(区间内不同的数之和)
- HDU 3333 Turing Tree (离线线段树,经典)
- hdu 3333 Turing Tree(线段树)
- hdu 3333 Turing Tree(线段树)
- HDU 3333 Turing Tree (离线询问+线段树)
- HDU 3333 Turing Tree(树状数组 || 线段树)
- HDU-3333-Turing Tree-离散化思想
- hdu 3333 Turing Tree (树状数组+离线处理+离散化)
- hdu 3333 Turing Tree 树状数组或者线段树
- HDU 3333 Turing Tree(离线线段树)
- hdu 3333 Turing Tree 线段树
- HDU-3333-Turing Tree(离线+哈希+树状数组|线段树)
- 【线段树+离散化+离线方法】杭电 hdu 3333 Turing Tree
- HDU 3333 Turing tree 用了一发map容器加线段树