bzoj3932 / P3168 [CQOI2015]任务查询系统(主席树+差分)
看到第k小,就是主席树辣
对于每一段任务(a,b,k),在版本a的主席树+k,版本b+1的主席树-k
同一时间可能有多次修改,所以开个vector存操作,再开个数组ti[p]保存时间点p最终的版本号
注意long long
#include<iostream> #include<cstdio> #include<cstring> #include<vector> using namespace std; typedef long long ll; inline int Abs(int a){return a<0?-a:a;} inline int Max(int a,int b){return a>b?a:b;} #define N 100005 #define W 20000005 int n,m,mx,u,tot,ti[N],rt[W],lc[W],rc[W],siz[W]; ll s[W],Pre=1; vector <int> g[N]; #define mid (l+r)/2 void Ins(int &o,int p,int l,int r,int v){ o=++u; siz[o]=siz[p]+(v>0?1:-1); s[o]=s[p]+v; if(l==r) return ; if(Abs(v)<=mid) rc[o]=rc[p],Ins(lc[o],lc[p],l,mid,v); else lc[o]=lc[p],Ins(rc[o],rc[p],mid+1,r,v); } ll Ask(int o,int l,int r,int k){ if(l==r) return 1ll*l*k; if(siz[lc[o]]>k) return Ask(lc[o],l,mid,k); else return s[lc[o]]+Ask(rc[o],mid+1,r,k-siz[lc[o]]); } int main(){ register int i,j; int q1,q2,q3,q4; scanf("%d%d",&n,&m); for(i=1;i<=n;++i){ scanf("%d%d%d",&q1,&q2,&q3); g[q1].push_back(q3); g[q2+1].push_back(-q3); mx=Max(mx,q3); } for(i=1;i<=n;++i){ for(j=g[i].size()-1;j>=0;--j) ++tot,Ins(rt[tot],rt[tot-1],1,mx,g[i][j]); ti[i]=tot; } for(i=1;i<=m;++i){ scanf("%d%d%d%d",&q1,&q2,&q3,&q4); q2=1+(q2*Pre+q3)%q4; q1=rt[ti[q1]]; Pre=q2<siz[q1]?Ask(q1,1,mx,q2):s[q1]; printf("%lld\n",Pre); }return 0; }