JOI 春合宿 2010 Day 3 Hide-and-seek(かくれんぼ)


obstacleたちをソートして、順番に処理していく。
足す作業はStarry Sky Treeでやる。後から思ったけど、別に遅延評価する必要ない。(2つの配列に分けてもできる、詳しくは蟻本参照)
最大値のindexの求め方がわかってからはやるだけだった…(つらい)

const int SIZE=1<<18;
struct segtree
{
	int seg[SIZE*2],lazy[SIZE*2];
	void lazy_evaluate(int k)
	{
		seg[k]+=lazy[k];
		if(k<SIZE-1)
		{
			lazy[k*2+1]+=lazy[k];
			lazy[k*2+2]+=lazy[k];
		}
		lazy[k]=0;
		return;
	}
	void update(int a,int b,int k,int l,int r,int x)
	{
		lazy_evaluate(k);
		if(r<=a||b<=l)return;
		else if(a<=l&&r<=b)
		{
			lazy[k]+=x;
			lazy_evaluate(k);
			return ;
		}
		else
		{
			update(a,b,k*2+1,l,(l+r)/2,x);
			update(a,b,k*2+2,(l+r)/2,r,x);
			seg[k]=max(seg[k*2+1],seg[k*2+2]);
			return;
		}
	}
	int get_max(){return seg[0]+lazy[0];}
	int find(int x)
	{
		if(x>get_max())return -1;
		int now=0;
		while(1)
		{
			lazy_evaluate(now);
			if(now>=SIZE-1)return now-(SIZE-1);
			int lch=now*2+1,rch=now*2+2;
			if(seg[lch]+lazy[lch]>=x)now=lch;
			else now=rch;
		}
	}
}sst;
struct obst
{
	int x,y,len;
};
bool comp(obst a,obst b)
{
	if(a.y!=b.y)return a.y < b.y;
	else return a.x < b.x;
}
int n,q;
int main()
{
	scanf("%d %d",&n,&q);
	vector<obst> vec(n);
	vector<P> query(q);
	vector<P> ans(q);
	for(int i=0;i<n;i++)cin >> vec[i].x >> vec[i].y >> vec[i].len;
	for(int i=0;i<q;i++)
	{
		cin >> query[i].fi;
		query[i].sec=i;
	}
	sort(vec.begin(),vec.end(),comp);
	sort(query.begin(),query.end());
	int pos=0;
	for(int i=0;i<vec.size();i++)
	{
		sst.update(vec[i].x,vec[i].x+vec[i].len,0,0,SIZE,1);
		//cout << i << ' ' << sst.get_max() << endl;
		while(pos<query.size()&&query[pos].fi<sst.get_max())
		{
			ans[query[pos].sec].sec=vec[i].y;
			ans[query[pos].sec].fi=sst.find(query[pos].fi+1);
			pos++;
		}
	}
	P na=P(0,0);
	for(int i=0;i<ans.size();i++)
	{
		if(ans[i]==na)cout << "-1 -1" << endl;
		else cout << ans[i].fi << ' ' << ans[i].sec << endl;
	}
	return 0;
}