当前位置: 代码迷 >> 综合 >> D-query SPOJ - DQUERY (主席树 or 树状数组,hash)
  详细解决方案

D-query SPOJ - DQUERY (主席树 or 树状数组,hash)

热度:10   发布时间:2024-01-22 01:50:20.0

题意:

给定一数组,查找区间上不同的数种类有多少。

题解:

好多把这道题看做模板题,但和曾经写过的一道树状数组题很像。这里提供两种解法:

主席树解法是记录重复的次数,然后最后总的去减。

#include<bits/stdc++.h>using namespace std;const int maxn = 30000+100;
const int maxm = 200000+100;
const int maxv = 1000000+100;
long long c[maxn];
int a[maxn];
long long ans[maxm];
struct node
{int l,r;int index;bool operator < (const node& a)const{return l<a.l;}
}ns[maxm];struct hashmap
{int head[maxv],next[maxn];void init(){memset(head,-1,sizeof head);}void inser(int i,int v){next[i] = -1;if(head[v]==-1)head[v]=i;else{int j = head[v];while(next[j]!=-1){j = next[j];}next[j] = i;}}int fin(int i){return next[i];}
}hm;long long sum(int x)
{long long res=0;while(x>0){res+=c[x];x-=(x&-x);}return res;
}void add(int x,int v)
{while(x<maxn){c[x]+=v;x+=(x&-x);}
}int main()
{int n,m;//cin>>t;while(~scanf("%d",&n)){hm.init();memset(c,0,sizeof c);for(int i=1;i<=n;i++){scanf("%d",a+i);if(hm.head[a[i]]==-1)add(i,1);hm.inser(i,a[i]);}cin>>m;for(int i=1;i<=m;i++){scanf("%d%d",&ns[i].l,&ns[i].r);ns[i].index=i;}sort(ns+1,ns+1+m);int j=1;for(int i=1;i<=n;i++){while(ns[j].l==i){ans[ns[j].index]=sum(ns[j].r);///找完所有的区间为L的区间j++;}if(j>m)break;///所有的区间找完了add(i,-1);///原来的位置减去1if(hm.fin(i)!=-1)///在新的位置加上1{add(hm.fin(i),1);}}for(int i=1;i<=m;i++){printf("%d\n",ans[i]);}}}

这份主席树直接拿来用了:

#include<bits/stdc++.h>using namespace std;
typedef long long LL;
#define lson l, m
#define rson m+1, r
const int N=30005;
int L[N<<5], R[N<<5], sum[N<<5];
int tot;
int a[N], T[N];
int read()//输入外挂
{char ch=' ';int ans=0;while(ch<'0' || ch>'9')ch=getchar();while(ch<='9' && ch>='0'){ans=ans*10+ch-'0';ch=getchar();}return ans;
}int build(int l, int r)
{int rt=(++tot);sum[rt]=0;if(l<r){int m=(l+r)>>1;L[rt]=build(lson);R[rt]=build(rson);}return rt;
}int update(int pre, int l, int r, int x)
{int rt=(++tot);L[rt]=L[pre], R[rt]=R[pre], sum[rt]=sum[pre]+1;if(l<r){int m=(l+r)>>1;if(x<=m)L[rt]=update(L[pre], lson, x);elseR[rt]=update(R[pre], rson, x);}return rt;
}int query(int u, int v, int l, int r, int k)
{if(l>=k)return sum[v]-sum[u];int m=(l+r)>>1;int ans=0;if(m>=k)ans+=query(L[u], L[v], lson, k);ans+=query(R[u], R[v], rson, k);return ans;
}int main()
{tot=0;int n=read();
//        scanf("%d", &n);for(int i=1; i<=n; i++){
//            scanf("%d", &a[i]);a[i]=read();}T[0]=0;map<int, int> mp;mp.clear();for(int i=1; i<=n; i++){if(mp.find(a[i])!=mp.end())T[i]=update(T[i-1], 1, n, mp[a[i]]);elseT[i]=T[i-1];mp[a[i]]=i;}int m=read();
//        scanf("%d", &m);while(m--){int l, r;l=read(), r=read();
//            scanf("%d%d", &l, &r);printf("%d\n", r-l+1-query(T[l-1], T[r], 1, n, l));}
}

  相关解决方案