hdu 3874 Necklace(离线操作+树状数组或线段树)
2015-08-21 23:21
429 查看
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=3874
解题思路:
我们可以先离线处理。先读入所有的查询,然后对所有查询按区间右端点从小到大排序,再依次进行处理,这样可以保证后面的操作不会改变前面的查询结果。使原序列中的数据一个一个的加入到线段树中,若某个数已经在序列中,则在最近出现的位置删除该数,这样就能保证每个数任意时刻只在线段树的中存储一次;若加入新的数据在线段树中对应的下标等于某个查询区间的右端点,则立即计算该查询区间的和。这样就能保证当前查询区间内没有重复的数,且该区间内的所有数都已加入到线段树中。树状数组的做法与线段树的大致一样。。。
AC代码(树状数组):
AC代码(线段树):
http://acm.hdu.edu.cn/showproblem.php?pid=3874
解题思路:
我们可以先离线处理。先读入所有的查询,然后对所有查询按区间右端点从小到大排序,再依次进行处理,这样可以保证后面的操作不会改变前面的查询结果。使原序列中的数据一个一个的加入到线段树中,若某个数已经在序列中,则在最近出现的位置删除该数,这样就能保证每个数任意时刻只在线段树的中存储一次;若加入新的数据在线段树中对应的下标等于某个查询区间的右端点,则立即计算该查询区间的和。这样就能保证当前查询区间内没有重复的数,且该区间内的所有数都已加入到线段树中。树状数组的做法与线段树的大致一样。。。
AC代码(树状数组):
#include <iostream> #include <cstdio> #include <cstring> #include <map> #include <algorithm> using namespace std; typedef long long ll; const int N = 50005; const int M = 200005; int n,m; ll a ; ll ans[M]; struct node{ int index,l,r; }q[M]; ll c ; //c[i] = a[i-lowbit(i)+1] + …+ a[i],下标从1开始 map<ll,int> mm; bool cmp(node x,node y){ return x.r < y.r; } int lowbit(int x){ return x&(-x); } void update(int x,ll val){ while(x <= n){ c[x] += val; x += lowbit(x); } } ll sum(int x){ ll ans = 0; while(x){ ans += c[x]; x -= lowbit(x); } return ans; } int main(){ int T; scanf("%d",&T); while(T--){ memset(c,0,sizeof(c)); mm.clear(); scanf("%d",&n); for(int i = 1; i <= n; i++) scanf("%lld",&a[i]); scanf("%d",&m); for(int i = 1; i <= m; i++){ scanf("%d%d",&q[i].l,&q[i].r); q[i].index = i; } sort(q+1,q+m+1,cmp); int id = 1; for(int i = 1; i <= n; i++){ update(i,a[i]); if(mm[a[i]]) update(mm[a[i]],-a[i]); mm[a[i]] = i; while(id <= m && q[id].r == i){ ans[q[id].index] = sum(q[id].r)-sum(q[id].l-1); id++; } } for(int i = 1; i <= m; i++) printf("%lld\n",ans[i]); } return 0; }
AC代码(线段树):
#include <iostream> #include <cstdio> #include <cstring> #include <map> #include <algorithm> using namespace std; typedef long long ll; const int N = 50005; const int M = 200005; int n,m; ll ans[M]; ll a ; struct Node{ int index,l,r; }q[M]; struct node{ int l,r; ll sum; }tree[N<<2]; void build(int id,int l,int r){ tree[id].l = l; tree[id].r = r; tree[id].sum = 0; if(l == r) return; int mid = (l+r)>>1; build(id<<1,l,mid); build(id<<1|1,mid+1,r); } void update(int id,int x,ll val){ tree[id].sum += val; if(tree[id].l == x && tree[id].r == x){ //tree[id].sum = val; return; } int mid = (tree[id].l+tree[id].r)>>1; if(x <= mid) update(id<<1,x,val); else update(id<<1|1,x,val); //tree[id].sum=tree[(id<<1)].sum+tree[(id<<1)|1].sum; } ll query(int id,int l,int r) { if(tree[id].l == l && tree[id].r == r) return tree[id].sum; int mid = (tree[id].l+tree[id].r)>>1; if(r <= mid) return query(id<<1,l,r); if(l >= mid+1) return query((id<<1)|1,l,r); return query(id<<1,l,mid) + query((id<<1)|1,mid+1,r); } bool cmp(Node x,Node y){ return x.r < y.r; } map<ll,int> mm; int main(){ int T; scanf("%d",&T); while(T--){ mm.clear(); scanf("%d",&n); for(int i = 1; i <= n; i++) scanf("%lld",&a[i]); build(1,1,n); scanf("%d",&m); for(int i = 1; i <= m; i++){ scanf("%d%d",&q[i].l,&q[i].r); q[i].index = i; } sort(q+1,q+m+1,cmp); int id = 1; for(int i = 1; i <= n; i++){ update(1,i,a[i]); if(mm[a[i]]) update(1,mm[a[i]],-a[i]); mm[a[i]] = i; while(id <= m && q[id].r == i){ ans[q[id].index] = query(1,q[id].l,q[id].r); id++; } } for(int i = 1; i <= m; i++) printf("%lld\n",ans[i]); } return 0; }
相关文章推荐
- 2015/08/21
- lncRNA研究
- F#相关图书推荐
- iOS开发所需英语词汇整理
- 2015-8-1(1)
- 模拟 nbut1225 NEW RDSP MODE I
- sqlite3 journal
- SPOJ 3267 DQUERY(主席树在线|树状数组离线)
- 鸟哥的Linux私房菜-----16、程序与资源管理
- 论软件设计中的哲学观
- 微信分享SDK导入报错 Undefined symbols for architecture i386:
- UISlider的使用
- Scala学习笔记--for,function,lazy用法小结
- Tomcat配置去掉项目名称,直接通过域名访问
- 32位与64位下各类型长度对比
- ORACLE RMAN下针对带库设备的操作
- Oracle 学习之 SQL(二) Restricting and Sorting Data
- mysql实现ORACLE的connect by prior父子递归查询
- NBUT 1452 Ezreal (模拟水题)
- 如何改变Xcode字体大小?