bzoj3932: [CQOI2015]任务查询系统(主席树)
[CQOI2015]任务查询系统
思路
按时间顺序建权值线段树,对于每个三元组,在Si的树上Pi的位置+1,Ei+1的树上Pi的位置-1,这样对于每次询问的时间区间T[r] - T[l-1]求前k个的和就行了,需要注意的是询问的时候当l==r时这个位置的值不能全部取走,要取走相应的剩下的那k个。
代码
#include
using namespace std;
#define dd(x) cout<<#x<<"="< vi;
typedef pair pi;
int T[maxn<<7], l[maxn<<7], r[maxn<<7];
ll sum[maxn<<7];
int cnt,s[maxn<<7], n, m;
vector vv;
vector < pair < int ,ll > > v;
void upd(int pre, int &now,int L,int R,int t,ll p){
now = ++cnt;
sum[now]=sum[pre]+p;
s[now]=s[pre]+p/abs(p);
l[now]=l[pre];
r[now]=r[pre];
if(L==R) return ;
int mid= L+R>>1;
if(t<=mid )upd(l[pre],l[now],L,mid,t,p);
else upd(r[pre],r[now],mid+1,R,t,p);
}
ll qr(int now ,int k,int L,int R ){
if(L==R){
return 1ll*k*sum[now]/s[now];
}
if(s[now]==0) return 0;
int mid = L+R>>1;
if(k>s[l[now]]) return qr(r[now], k-s[l[now]],mid+1,R)+sum[l[now]];
return qr(l[now],k,L,mid);
}
int main(){
ios_base::sync_with_stdio(0);
cin.tie(0);
cin>> n>> m;
rep(i,0,n){
int l,r;
ll p;
cin>> l >> r>> p;
v.pb({l,p});
v.pb({r+1,-p});
vv.pb(p);
}
sort(all(vv));
vv.erase(unique(all(vv)),vv.end());
int t=0, mm=sz(vv);
sort(all(v));
rep(i,1,m+1){
T[i] = T[i-1];
while(t>x>>a>> b>> c;
pre%=c;
k = 1+(a*pre%c+b)%c;
if(k> s[T[x]] ) pre = 1ll*sum[T[x]];
else pre=qr(T[x],k,1,sz(vv));
cout << pre << endl;
}
return 0;
}