[BZOJ3110][Zjoi2013]K大数查询(主席数套线段树 )
发布时间:2021-03-15 22:16:09 所属栏目:大数据 来源:网络整理
导读:题目描述 传送门 题解 外层权值线段树,权值线段树的每一个位置都是一棵线段树,线段树用动态开点。 注意pushdown或者查询的时候还有可能要继续开点。 注意最顶端的点的权有可能是炸了int了,因为有可能加入了50000^2个点。 代码 #includealgorithm#includei
题目描述传送门 题解外层权值线段树,权值线段树的每一个位置都是一棵线段树,线段树用动态开点。 代码#include<algorithm> #include<iostream> #include<cstring> #include<cstdio> using namespace std; #define LL long long const int max_n=1e6+5; const int max_tree=2e7+5; int n,m,opt,cnt,N,t,ans,sz; int A[max_n],B[max_n],C[max_n],number[max_n],hash[max_n];bool flag[max_n]; int root[max_n],ls[max_tree],rs[max_tree]; LL sum[max_tree],delta[max_tree]; inline int find(int x){ int l=1,r=N,mid; while (l<=r){ mid=(l+r)>>1; if (x>hash[mid]) l=mid+1; else r=mid-1; } return l; } inline void modify(int now){ sum[now]=sum[ls[now]]+sum[rs[now]]; } inline void pushdown(int now,int l,int r,int mid){ if (delta[now]){ if (!ls[now]) ls[now]=++sz; sum[ls[now]]+=delta[now]*(mid-l+1); delta[ls[now]]+=delta[now]; if (!rs[now]) rs[now]=++sz; sum[rs[now]]+=delta[now]*(r-mid); delta[rs[now]]+=delta[now]; delta[now]=0; } } inline void update(int last,int &now,int lrange,int rrange,LL v){ int mid=(l+r)>>1; if (!now) now=++sz; ls[now]=ls[last]; rs[now]=rs[last]; if (lrange<=l&&r<=rrange){ sum[now]+=v*(r-l+1); delta[now]+=v; return; } pushdown(now,l,r,mid); if (lrange<=mid) update(ls[last],ls[now],mid,lrange,rrange,v); if (mid+1<=rrange) update(rs[last],rs[now],mid+1,v); modify(now); } inline LL query(int now,int rrange){ int mid=(l+r)>>1;LL ans=0; if (lrange<=l&&r<=rrange) return sum[now]; pushdown(now,mid); if (lrange<=mid) ans+=query(ls[now],rrange); if (mid+1<=rrange) ans+=query(rs[now],rrange); return ans; } inline void v_update(int now,int x,int rrange){ int mid=(l+r)>>1; update(root[now],root[now],1,n,1); if (l==r) return; if (x<=mid) v_update(now<<1,x,rrange); else v_update(now<<1|1,rrange); } inline int v_query(int now,LL k){ if (!now) return 0; int mid=(l+r)>>1; if (l==r) return l; LL t=query(root[now<<1],rrange); if (t>=k) return v_query(now<<1,k); else return v_query(now<<1|1,k-t); } int main(){ scanf("%d%d",&n,&m); for (int i=1;i<=m;++i){ scanf("%d%d%d%d",&opt,&A[i],&B[i],&C[i]); if (opt==1) flag[i]=true,number[++cnt]=C[i]; } sort(number+1,number+cnt+1); for (int i=1;i<=cnt;++i) if (number[i]!=number[i-1]) hash[++N]=number[i]; for (int i=1;i<=m;++i) if (flag[i]){ t=find(C[i]); v_update(1,A[i],B[i]); } else{ LL tot=query(root[1],B[i]); LL t=(LL)tot-(LL)C[i]+1; ans=v_query(1,B[i],t); printf("%dn",hash[ans]); } } 总结这种动态开点点数和空间的计算十分蛋疼。 (编辑:晋中站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |