SPOJ DQUERY D-query(離線線段樹,查區間不同數字個數)
阿新 • • 發佈:2019-02-13
題意:
找區間不同數字
思路:
先把所有操作記錄下來,之後按查詢的右端點排序,如果數字存在update -1 否則udpate+1
#include <iostream> #include <stdio.h> #include <map> #include <algorithm> using namespace std; const int maxn=300005; struct node { int l,r,sum; } tree[maxn*4]; struct ques { int l,r,index; }ask[maxn]; int a[maxn]; int ans[maxn]; void build(int i,int left,int right) { tree[i].l=left,tree[i].r=right; tree[i].sum=0; if(left==right) return; int mid=left+right>>1; build(i<<1,left,mid); build(i<<1|1,mid+1,right); } map<int,int> has; void update(int i,int pos ,int w) { if(tree[i].l==pos&&tree[i].r==pos) { tree[i].sum+=w; return ; } int mid=(tree[i].l+tree[i].r)>>1; if(pos<=mid) update(i<<1,pos ,w); else update(i<<1|1,pos ,w); tree[i].sum=tree[i<<1].sum+tree[i<<1|1].sum; } int query(int i,int left,int right) { if(tree[i].l==left&&tree[i].r==right) { return tree[i].sum; } int mid=(tree[i].l+tree[i].r)>>1; if(right<=mid) return query(i<<1,left,right); else if(left>mid) return query(i<<1|1,left,right); else return query(i<<1,left,mid)+query(i<<1|1,mid+1,right); } bool cmp(ques a,ques b) { return a.r<b.r; } int main() { int n; scanf("%d",&n); build(1,1,n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); int m; scanf("%d",&m); for(int i=1;i<=m;i++) { ask[i].index=i; scanf("%d%d",&ask[i].l,&ask[i].r); } sort(ask+1,ask+1+m,cmp); int cur=1; for(int i=1;i<=m;i++) { for(int j=cur;j<=ask[i].r;j++) { if(has.find(a[j])!=has.end()) { int p=has[a[j]]; update(1,p ,-1); } update(1,j, 1); has[a[j]]=j; } cur=ask[i].r+1; ans[ask[i].index]=query(1,ask[i].l,ask[i].r); } for(int i=1;i<=m;i++) printf("%d\n",ans[i]); }