http://acm.hdu.edu.cn/showproblem.php?pid=3874
这题题目是好题呀!可以我想不出来,看了网上的题解才明白!
当时我想的是枚举从1 到 当前 r 区间中只出现一次的和,但是对于 询问 【l ,r】就 如果某个数在 只在[ 1 , L-1] 或者 [ l , r ] 区间出现答案都正确,但是对于 有些数 在两个区间都出现的话,一减的话相当于没有出现,答案就不对了…… 看了网上的解题办法,是这样的话,如果当前的数之前出现的话,那么把之前的位置处减去,然后再当前位置插入……
离线查询
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define lowbit(x) x&(-x) const int maxn=500100; typedef long long ll; ll d[maxn],ans[maxn]; int n,last[1000010],a[maxn]; struct Node { int l,r,id; }node[200010]; int cmp(Node a,Node b) { if(a.r!=b.r) return a.r < b.r; return a.l < b.l; } void add(int p,int val) { for(int i=p;i<=n;i+=lowbit(i)) d[i]+=val; } ll query(int p) { ll sum=0; for(int i=p;i>=1;i-=lowbit(i)) sum+=d[i]; return sum; } int main() { int m,ca; scanf("%d",&ca); while(ca--) { scanf("%d",&n); memset(d,0,sizeof(d)); memset(last,-1,sizeof(last)); for(int i=1;i<=n;i++) scanf("%d",&a[i]); scanf("%d",&m); for(int i=0;i<m;i++) scanf("%d %d",&node[i].l,&node[i].r),node[i].id=i; sort(node,node+m,cmp); int r=1; for(int i=0;i<m;i++) { while(r<=node[i].r) { if(last[a[r]]!=-1) add(last[a[r]],-a[r]); last[a[r]]=r; add(r,a[r]); r++; } ans[node[i].id]=query(node[i].r)-query(node[i].l-1); } for(int i=0;i<m;i++) printf("%I64d\n",ans[i]); } return 0; }