洛谷 P3168 [CQOI2015]任務查詢系統 主席樹
阿新 • • 發佈:2018-12-14
這個主席樹的題很多人寫題解,但是我想寫一份程式碼足夠簡潔的題解,思路很簡單,對於每個區間 l r p,我們用差分陣列,分別記錄左端點和右端點即可,如果不會差分陣列建議去刷一下南陽oj士兵殺敵5,差分陣列模板題,然後差分陣列的字首和就是每個時間點所含有的任務資訊了,接下來用主席樹模板即可。
#include<cstdio> #include<algorithm> using namespace std; const int maxn=2e5+10; typedef long long ll; struct node { int pos,k,v; bool operator<(const node& t)const { return pos<t.pos; } }a[maxn]; int b[maxn],rt[maxn],ls[maxn*20],rs[maxn*20],sum[maxn*20]; ll ans[maxn*20]; int cnt=0,sz=0; void up(int pre,int &o,int l,int r,int k,int v) { o=++cnt; sum[o]=sum[pre]+v; ans[o]=ans[pre]+v*b[k]; ls[o]=ls[pre]; rs[o]=rs[pre]; if(l==r)return; int m=(l+r)/2; if(k<=m)up(ls[pre],ls[o],l,m,k,v); else up(rs[pre],rs[o],m+1,r,k,v); } ll qu(int o,int l,int r,int k) { if(k>=sum[o])return ans[o]; if(l==r)return 1ll*b[l]*k; int m=(l+r)/2,res=sum[ls[o]]; if(k<=res)return qu(ls[o],l,m,k); else return ans[ls[o]]+qu(rs[o],m+1,r,k-res); } int main() { int n,m,l,r,x; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%d%d%d",&l,&r,&b[i]); a[i].pos=l,a[i].k=b[i],a[i].v=1; a[i+n].pos=r+1,a[i+n].k=b[i],a[i+n].v=-1; } sort(b+1,b+1+n); sz=unique(b+1,b+1+n)-b-1; sort(a+1,a+1+2*n); for(int i=1;i<=2*n;i++)a[i].k=lower_bound(b+1,b+1+sz,a[i].k)-b; for(int i=1;i<=2*n;i++) up(rt[a[i-1].pos],rt[a[i].pos],1,sz,a[i].k,a[i].v); for(int i=1;i<=n;i++)if(!rt[i])rt[i]=rt[i-1]; ll pre=1,A,B,C; for(int i=1;i<=m;i++) { scanf("%d%lld%lld%lld",&x,&A,&B,&C); int k=1+(A*pre+B)%C; printf("%lld\n",pre=qu(rt[x],1,sz,k)); } }