题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3874
2 6 1 2 3 4 3 5 3 1 2 3 5 2 6 6 1 1 1 2 3 5 3 1 1 2 4 3 5
3 7 14 1 3 6
题意:
求给出的每个区间的和,注意所求区间里相同的数只计算一次!
例如:1 1 1 2 3 1, F(1,3)=1, F(2,4)=3, F(2,6)=6.
PS:
离线算法:先按询问的右端点排序,然后依次把数字插入到线段树里,用pre[i]记录数字 i 上一次出现的位置,如果 i 已经出现过,删除之前的,并且添加到当前的位置。遇到可以处理的询问则处理,同时存储结果。
代码如下:
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define lson l , mid , rt << 1 #define rson mid + 1 , r , rt << 1 | 1 #define LL __int64 const int maxn = 111111; LL add[maxn<<2];//用来标记每个节点,为0则表示没有标记,否则为标记; LL sum[maxn<<2];//求和 struct node { int l, r; int id; bool operator < (const node &a)const { return r < a.r; } } e[maxn<<1]; void PushUp(int rt) //把当前结点的信息更新到父结点 { sum[rt] = sum[rt<<1] + sum[rt<<1|1]; } void build(int l,int r,int rt) { add[rt] = 0;//初始化为所有结点未被标记 sum[rt] = 0; if(l == r) { //scanf("%lld",&sum[rt]); return ; } int mid = (l + r) >> 1; build(lson); build(rson); PushUp(rt); } void update(int p,int sc,int l,int r,int rt) { if(l == r) //叶节点 { sum[rt] = sc; return ; } int mid = (l + r) >> 1; if(p <= mid)//递归更新左子树或者右子树 update(p , sc , lson); else update(p , sc , rson); PushUp(rt); } LL query(int L,int R,int l,int r,int rt) { if(L <= l && r <= R) { return sum[rt]; } int mid = (l + r) >> 1; LL ret = 0; if (L <= mid) ret += query(L , R , lson); if (mid < R) ret += query(L , R , rson); return ret; } int pre[1000010], a[maxn]; LL ans[maxn<<1]; int main() { int N , Q; int t; scanf("%d",&t); while(t--) { memset(pre,-1,sizeof(pre)); scanf("%d",&N);//N为节点数 for(int i = 1; i <= N; i++) { scanf("%d",&a[i]); } build(1, N, 1); //建树 scanf("%d",&Q); for(int i = 1; i <= Q; i++) { scanf("%d%d",&e[i].l,&e[i].r); e[i].id = i; } sort(e+1, e+Q+1); for(int i=1, j=1; i<=N && j<=Q; i++) { if(pre[a[i]]!=-1) update(pre[a[i]],0,1,N,1); update(i,a[i],1,N,1);//把i的成绩更为a[i] while(j<=Q && e[j].r<=i) { if(e[j].r == i) ans[e[j].id]=query(e[j].l,e[j].r,1,N,1); j++; } pre[a[i]]=i; } for(int i = 1; i <= Q; i++) { printf("%I64d\n",ans[i]); } } return 0; } /* 2 6 1 2 3 4 3 5 3 1 2 2 6 3 5 6 1 1 1 2 3 5 3 1 1 2 4 3 5 */