hdu_3874 Necklace
2013-08-23 10:20
381 查看
原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=3874
分析:线段树,区间内不重复数的和。
1、 用vis[]数组记录将要插入的数是否在线段树中,在的话就删除(在相应的位置减去这个数)原来位置的值,将这个值插到现在的位置。
如:1 1 1 2 3 5 插入第二个1的是好,第一个1在线段树[1,1]的位置,这是先删除[1,1]位置的1,再插入第二个1.
2、 询问之前先对所有的询问数据按右端点升序排序,这样就可以防止不断删除、插入的混乱(可以模拟一次,看看效果)。
我的代码:
总结:这算是简单的离散化,线段树了。
分析:线段树,区间内不重复数的和。
1、 用vis[]数组记录将要插入的数是否在线段树中,在的话就删除(在相应的位置减去这个数)原来位置的值,将这个值插到现在的位置。
如:1 1 1 2 3 5 插入第二个1的是好,第一个1在线段树[1,1]的位置,这是先删除[1,1]位置的1,再插入第二个1.
2、 询问之前先对所有的询问数据按右端点升序排序,这样就可以防止不断删除、插入的混乱(可以模拟一次,看看效果)。
我的代码:
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; #define MAXN 50005 #define MAXM 200005 typedef __int64 LL; struct Node { int l,r; LL sum; }segtree[MAXN<<2]; struct piont { int x,y; int i; bool operator <(const piont & a)const{ return y<a.y; } }cood[MAXM]; const int NUM=1000005; //最大的价值。 int p[MAXN]; //输入的项链价值。 int vis[NUM];//表示M这个数在线段树中得位置。 LL ans[MAXM]; //存放每次询问的答案。 void build(int i,int s,int e) { segtree[i].l=s; segtree[i].r=e; segtree[i].sum=0; if(s==e) return ; int mid=(s+e)>>1; build( 2*i, s, mid); build( 2*i+1,mid+1, e); } void Modfiy(int i,int add,int y) //在y的位置更新sum的值为ADD,插入为+,删除为-; { if(y==segtree[i].l&&y==segtree[i].r) { segtree[i].sum+=add; return ; } int mid=(segtree[i].l+segtree[i].r)>>1; if(y<=mid) { Modfiy(2*i, add, y); } else { Modfiy(2*i+1, add, y); } segtree[i].sum+=add; } __int64 query(int i,int x,int y) { if(segtree[i].l==x&&y==segtree[i].r) return segtree[i].sum; int mid=(segtree[i].l+segtree[i].r)>>1; if(y <= mid) { return query( 2*i, x, y); } else if(x>mid) return query( 2*i+1, x, y); else { return query( 2*i, x, mid)+query( 2*i+1, mid+1, y); } } int main() { int t; scanf("%d",&t); while(t--) { int n,m; scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",p+i); scanf("%d",&m); for(int i=1;i<=m;i++) { scanf("%d%d",&cood[i].x,&cood[i].y); cood[i].i=i; } sort(cood+1,cood+1+m); build(1,1,n); memset(vis,0,sizeof(vis)); int j=1; //输入的下标。 for(int i=1;i<=m;i++) { while(j<=cood[i].y) //还没有到询问值。 {//p[j]这个数已经在线段树中,vis[i]=j,i这个在线段树的j位置,。 if(vis[p[j]]) Modfiy(1,-p[j],vis[p[j] ]); Modfiy(1,p[j],j); vis[p[j]]=j; //表示插到了j 这个点。 j++; } ans[cood[i].i]= query(1,cood[i].x,cood[i].y); } for(int i=1;i<=m;i++) { printf("%I64d\n",ans[i]); } } return 0; }
总结:这算是简单的离散化,线段树了。
相关文章推荐
- HDU 3874 Necklace 树状数组
- hdu 3874 Necklace
- HDU 3874 Necklace (树状数组 | 线段树 的离线处理)
- 【HDU - 3874 Necklace】 线段树
- hdu 3874 Necklace(树状数组的灵活应用)
- HDU - 3874Necklace(线段树离线查询)
- 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(树状数组+离线操作)
- hdu 3874 Necklace(线段树)
- HDU 3874 Necklace
- HDU 3874 Necklace
- HDU 3874 Necklace 树状数组