1. 程式人生 > 實用技巧 >#主席樹,離散,掃描線#洛谷 3168 [CQOI2015]任務查詢系統

#主席樹,離散,掃描線#洛谷 3168 [CQOI2015]任務查詢系統

題目


分析

詢問顯然得預處理,考慮以優先順序建權值線段樹,
將優先順序離散化處理,那麼第\(k\)大可以用線段樹來求
那任務怎麼辦,考慮時間用掃描線的方法,按照時間建新的線段樹
把任務分成兩部分,在兩端差分,實際上每次修改只會修改一小部分,
所以用主席樹做,空間複雜度就能得到保證


程式碼

#include <cstdio>
#include <cctype>
#include <algorithm>
#define rr register
using namespace std;
typedef long long lll; 
const int N=100011;
int n,m,T,b[N],rt[N];
struct rec{int x,p;}a[N<<1];
struct Chair{
    lll ww[N<<6],wc[N<<6];
	int ls[N<<6],rs[N<<6],cnt;
    inline void build(int &rt,int l,int r){
    	rt=++cnt,ww[rt]=wc[rt]=0;
    	if (l==r) return;
    	rr int mid=(l+r)>>1;
    	build(ls[rt],l,mid);
    	build(rs[rt],mid+1,r);
	}
	inline void update(int &rt,int l,int r,int x,int z){
		rr int trt=++cnt;
		ls[trt]=ls[rt],rs[trt]=rs[rt],
		ww[trt]=ww[rt],wc[trt]=wc[rt],rt=trt;
		if (l==r){
			wc[rt]+=z,ww[rt]+=z*b[l];
			return;
		}
		rr int mid=(l+r)>>1;
		if (x<=mid) update(ls[rt],l,mid,x,z);
		    else update(rs[rt],mid+1,r,x,z);
		wc[rt]=wc[ls[rt]]+wc[rs[rt]],
		ww[rt]=ww[ls[rt]]+ww[rs[rt]];
	}
	inline lll query(int rt,int l,int r,int kth){
		if (l==r) return kth*b[l];
		rr int mid=(l+r)>>1;
		return kth<=wc[ls[rt]]?query(ls[rt],l,mid,kth):
		    query(rs[rt],mid+1,r,kth-wc[ls[rt]])+ww[ls[rt]];
	}
}Tre;
inline signed iut(){
	rr int ans=0; rr char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
	return ans;
}
inline void print(lll ans){
	if (ans>9) print(ans/10);
	putchar(ans%10+48);
}
bool cmp(rec a,rec b){return a.x<b.x;}
signed main(){
	m=iut()<<1,T=iut(),Tre.cnt=0;
	for (rr int i=1;i<=m;i+=2){
		a[i].x=iut(),a[i+1].x=iut()+1,
		a[i].p=iut(),a[i+1].p=-a[i].p,
		b[++n]=a[i].p;
	}
	sort(b+1,b+1+n),sort(a+1,a+1+m,cmp),
	n=unique(b+1,b+1+n)-b-1,Tre.build(rt[0],1,n);
	for (rr int i=1,j=0;i<=m;++i){
		rr int op=1; if (a[i].p<0) op=-1,a[i].p*=op;
		for (;j<a[i].x;++j) rt[j+1]=rt[j]; if (j==T+1) break;
		rr int t=lower_bound(b+1,b+1+n,a[i].p)-b;
		Tre.update(rt[j],1,n,t,op);
	}
	for (rr lll lans=1;T;--T){
		rr int X=iut(),A=iut(),B=iut(),C=iut();
		rr int kth=1+(1ll*A*lans+B)%C;
		if (Tre.wc[rt[X]]<=kth) lans=Tre.ww[rt[X]];
		    else lans=Tre.query(rt[X],1,n,kth);
		print(lans),putchar(10);
	}
	return 0;
}