HDU3874

来源:互联网 发布:虚与委蛇 知乎 编辑:程序博客网 时间:2024/05/21 06:22

题目来源:http://acm.hdu.edu.cn/showproblem.php?pid=3874

树状数组+离线。

离线是看别人的代码看懂的。

先将所有的区间按左端点排序,判断目前的颜色是否在[l,pos]内出现过,如果出现过,则进行一次更新。

在[l,r]区间内未出现的颜色会在求和是减掉,所以不会有未出现的且不会有重复的。

代码看不懂的时候,搞组数据模拟一下就能懂了,离线我就是这样学的。

代码:

#include <cstdio>#include <iostream>#include <algorithm>#include <cstring>#include <cstdlib>#include <queue>#include <map>#include <vector>using namespace std;const int maxn=5e4+10;const int maxq=2e5+10;int n;int q;map<int,int> h;int a[maxn];__int64 tree[maxn];struct data{int l,r,id;}e[maxq];__int64 ans[maxq];int cmp(data a,data b){return a.r<b.r;}int lb(int x){return x&-x;}__int64 read(int x){__int64 tot=0;for(;x;x-=lb(x))tot+=tree[x];return tot;}void add(int num,int x){for(;x<=n;x+=lb(x))tree[x]+=num;}int main(){int _;scanf("%d",&_);while(_--){memset(tree,0,sizeof(tree));scanf("%d",&n);for(int i=1;i<=n;i++)scanf("%d",&a[i]);scanf("%d",&q);for(int i=1;i<=q;i++){scanf("%d%d",&e[i].l,&e[i].r);e[i].id=i;}h.clear();int pos=1;sort(e+1,e+1+q,cmp);for(int i=1;i<=q;i++){while(pos<=e[i].r){if(h[a[pos]]!=0)add(-a[pos],h[a[pos]]);add(a[pos],pos);h[a[pos]]=pos;pos++;}ans[e[i].id]=read(e[i].r)-read(e[i].l-1);}for(int i=1;i<=q;i++)printf("%lld\n",ans[i]);}return 0;}


原创粉丝点击