SPOJ DQUERY 主席树+lazy+乱搞
2015-04-10 09:26
267 查看
题意要求a,b区间中不同数的个数。
我们从头往后扫,对于前面已经出现过的我们不用管,因为我们现在要的是加入扫到p这个店就求以这个点为结尾的查询,至于之前已经出现过的加入出现在q,那么得在q~p-1每个数减一用lazy维护。
我们从头往后扫,对于前面已经出现过的我们不用管,因为我们现在要的是加入扫到p这个店就求以这个点为结尾的查询,至于之前已经出现过的加入出现在q,那么得在q~p-1每个数减一用lazy维护。
#include<cstdio> #include<algorithm> #include<cstring> #include<iostream> #include<map> #include<vector> using namespace std; const int maxn=30015; struct pi{ int sum; int lson; int rson; }pp[maxn*20]; int root[maxn],tot; void build(int cnt,int le,int ri){ pp[cnt].sum=0; if(le==ri) return ; tot++; pp[cnt].lson=tot; build(tot,le,(le+ri)/2); tot++; pp[cnt].rson=tot; build(tot,(le+ri)/2+1,ri); } void merg(int qq,int cnt,int n,int p,int k){ int le,ri,mid; le=1; ri=n; while(le<=ri){ pp[cnt]=pp[qq]; pp[cnt].sum+=k; if(le==ri) break; mid=(le+ri)/2; if(p<=mid){ pp[cnt].lson=tot+1; cnt=tot+1; qq=pp[qq].lson; tot++; ri=mid; } else{ pp[cnt].lson=tot+1; cnt=tot+1; qq=pp[qq].rson; tot++; le=mid+1; } } } int a[maxn],b[maxn]; struct ppi{ int x,y,id; }pp1[maxn*10]; struct pppi{ int le; int ri; int lazy; int sum; }pp2[maxn<<2]; void build1(int tot,int le,int ri){ pp2[tot].le=le; pp2[tot].ri=ri; pp2[tot].lazy=0; pp2[tot].sum=0; if(le==ri) return ; build1(2*tot,le,(le+ri)/2); build1(2*tot+1,(le+ri)/2+1,ri); } void merg1(int tot,int l,int r,int k){ if(pp2[tot].le>=l&&pp2[tot].ri<=r){ pp2[tot].lazy+=k; return ; } int mid=(pp2[tot].le+pp2[tot].ri)/2; pp[tot].sum+=k*(min(r,pp2[tot].ri)-max(l,pp2[tot].le)+1); if(l<=mid) merg1(2*tot,l,r,k); if(r>mid) merg1(2*tot+1,l,r,k); } int query1(int tot,int l,int r){ if(pp2[tot].le>=l&&pp2[tot].ri<=r){ return pp2[tot].lazy*(pp2[tot].ri-pp2[tot].le+1)+pp2[tot].sum; } int s=0,mid=(pp2[tot].le+pp2[tot].ri)/2; if(l<=mid) s+=query1(2*tot,l,r); if(r>mid) s+=query1(2*tot+1,l,r); s+=pp2[tot].lazy*(min(pp2[tot].ri,r)-max(pp2[tot].le,l)+1); return s; } int c[maxn*10]; int cmp(ppi a,ppi b){ return a.y<b.y; } vector<ppi >g[maxn]; map<int,int>mm; int main() { int i,j,n,m; cin>>n; tot=0; root[0]=0; build(0,1,n); for(i=1;i<=n;i++){ scanf("%d",&a[i]); b[i]=a[i]; } sort(b+1,b+1+n); for(i=1;i<=n;i++){ a[i]=(int)(lower_bound(b+1, b+1+n,a[i])-b); } cin>>m; for(i=0;i<m;i++){ scanf("%d%d",&pp1[i].x,&pp1[i].y); pp1[i].id=i; } sort(pp1,pp1+m,cmp); for(i=0;i<m;i++){ g[pp1[i].y].push_back(pp1[i]); } mm.clear(); build(0,1,n); build1(1,1,n); root[0]=0; for(i=1;i<=n;i++){ if(mm[a[i]]){ merg1(1,mm[a[i]],i-1,-1); root[i]=root[i-1]; } else{ root[i]=tot+1; tot++; merg(root[i-1],root[i],n,a[i],1); } mm[a[i]]=i; int p=g[i].size(); for(j=0;j<p;j++){ c[g[i][j].id]=pp[root[i]].sum-pp[root[g[i][j].x-1]].sum-query1(1,g[i][j].x-1,g[i][j].x-1); } } for(i=0;i<m;i++){ printf("%d\n",c[i]); } }
相关文章推荐
- BZOJ 1803: Spoj1487 Query on a tree III 主席树题解
- SPOJ DQUERY (离线数状数组||在线主席树)
- SPOJ DQUERY (主席树模板)
- SPOJ 3267(DQUERY) D-query 【主席树】【离线树状数组】
- SPOJ - DQUERY 主席树求区间中不同数字的个数
- 【SPOJ3267】D-query-主席树应用
- SPOJ-DQUERY-主席树求区间不同数个数模板
- SPOJ DQUERY D-query (主席树)
- SPOJ DQUERY 求区间内不同数的个数 主席树
- SPOJ 3267. D-query (主席树,查询区间有多少个不相同的数)
- SPOJ DQUERY - D-query [树状数组+离线 || 主席树 ]【数据结构】
- SPOJ DQUERY (离线数状数组||在线主席树)
- SPOJ3267 D-Query 树状数组离线操作 或 主席树 查询某一区间内有多少不同的数
- SPOJ Query on a tree III (树剖(dfs序)+主席树 || Splay等平衡树)(询问点)
- SPOJ DQUERY D-query(主席树)
- SPOJ DQUERY - D-query(主席树-区间不同数的个数)
- SPOJ D-query 主席树在线(求区间不同的数的个数)
- SPOJ - DQUERY 主席树求区间有多少个不同的数(模板)
- SPOJ 3267. D-query (主席树or树状数组离线)
- SPOJ 3267 DQUERY - D-query (主席树)(区间数的种数)