BZOJ3932(主席树上二分+差分
按时间作为主席树的版本,每个版本的主席树都是一个权值线段树。
差分消去时间影响
对于当前时间版本的主席树查询前K大即可。
树上二分时结束后切记判定l==r的状态(易错
l==r叶子节点可能存在多个值(值大小为sum/siz )
用I64dOLE了好久 。。 。。。。 。 。。 。 。 。 。 。 。 。 。。 。
用bit/stdc++.h CE.....
#include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; typedef long long ll; const int N = 301500; const int LOGN = 35; const int maxn = N*LOGN; #define lson son[rt][0] #define rson son[rt][1] #define un(x) (x>0?x:-x) struct node{ int pos,val; }; node cf[N<<1]; ll sum[maxn],siz[maxn]; int son[maxn][2],root[N],id[N]; void pushup(int rt) { siz[rt] = siz[lson]+siz[rson]; sum[rt] = sum[lson]+sum[rson]; } int tot = 0; void update(int x,int& y,int l,int r,int p) { y = ++tot; if(l==r) { if(p>0) siz[y] = siz[x]+1; else siz[y] = siz[x]-1; sum[y] = sum[x]+p; return ; } son[y][0] = son[x][0]; son[y][1] = son[x][1]; int m = (r+l)>>1; if(un(p)<=m) update(son[x][0],son[y][0],l,m,p); else update(son[x][1],son[y][1],m+1,r,p); pushup(y); } ll bfind(int l,int r,int rt,int k) { //cout<<"size:: "<<siz[rt]<<sum[rt]<<endl; if(siz[rt]<=k) return sum[rt]; ll ans = 0; while(l<r) { int m = (r+l)>>1; if(k<siz[lson]) { r = m; rt = lson; } else{ l = m+1; k -= siz[lson]; ans+=sum[lson]; rt = rson; } } if(k&&siz[rt]>0) ans+=sum[rt]/siz[rt]*min(k,siz[rt]); return ans; } bool cmp(node a,node b) { return a.pos<b.pos; } int main() { int n,m; scanf("%d%d",&m,&n); int s,e,p; int lim = 0; int cnt = 0; for(int i=0;i<m;i++){ scanf("%d%d%d",&s,&e,&p); cf[++cnt] = (node){s,p}; cf[++cnt] = (node){e+1,-p}; lim = max(lim,p); } sort(cf+1,cf+cnt+1,cmp); ll pre = 1; for(int i=1;i<=cnt;i++)update(root[i-1],root[i],1,lim,cf[i].val); for(int i=cnt;i>=1;i--){ if(cf[i].pos!=cf[i+1].pos) id[cf[i].pos] = i; } for(int i=1;i<=n;i++){ if(id[i]==0)id[i] = id[i-1]; //cout<<id[i]<<endl; } int x,a,b,c,k; for(int i=0;i<n;i++) { scanf("%d%d%d%d",&x,&a,&b,&c); k = (a*pre+b)%c+1; pre = bfind(1,lim,root[id[x]],k); //cout<<x<<" "<<id[x]<<" "; printf("%lld\n",pre); } return 0; }