HDU - 4866 Shooting(主席树+扫描线)

题目链接:点击查看

题目大意:给出 n 条平行于 x 轴的线段,每条线段都的 [ l , r ] 都位于 [ 1 , X ] 之间,每条线段的高度为 d,也就是距离 x 轴的位置,接下来给出 m 次询问,每次询问给出一个 x 和 k ,问:在点 x 处向上的前 k 个线段的高度之和为多少,如果 k 大于点 x 处的线段总数,那么缺少的线段用最高的线段的高度补上

题目分析:因为题目要求了强制在线,所以不能用线段树+离线来完成,区间 [ 1 , X ] 上的每个点可以通过扫描线的思想,将 n 条线段的属性转换为前缀和的思想,这样每个点都可以独立成为一个前缀和的版本了,所有的版本可以利用主席树来维护,每个版本中维护当前所有线段高度的前缀和,这样每次查询时,只需要查询第 x 个版本的主席树,在内部二分找到 k 的位置,然后返回前缀即可,对于 k 不足的地方,在 l == r 的地方稍微处理一下就可以了

代码:
 

#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
using namespace std;

typedef long long LL;

typedef unsigned long long ull;

const int inf=0x3f3f3f3f;

const int N=1e5+100;

vector<int>v,node[N];
/*主席树*/
struct Node
{
	int l,r,num;
	LL sum;
}tree[N*50];
 
int cnt,root[N];
 
void init()
{
	root[0]=0;
	tree[0].l=tree[0].r=tree[0].sum=tree[0].num=0;
	cnt=1;
}
 
void update(int pos,int flag,int &k,int l,int r)
{
	tree[cnt++]=tree[k];
	k=cnt-1;
	tree[k].num+=flag;
	tree[k].sum+=flag*v[pos-1];
	if(l==r)
		return;
	int mid=l+r>>1;
	if(pos<=mid)
		update(pos,flag,tree[k].l,l,mid);
	else
		update(pos,flag,tree[k].r,mid+1,r);
}
 
LL query(int rt,int k,int l,int r)
{
	if(l==r)
		return 1LL*v[l-1]*k;
	int mid=l+r>>1;
	int num=tree[tree[rt].l].num;
	LL sum=tree[tree[rt].l].sum;
	if(num>=k)
		return query(tree[rt].l,k,l,mid);
	else
		return sum+query(tree[rt].r,k-num,mid+1,r);
}
/*主席树*/
/*离散化*/ 
void discreate()
{
	sort(v.begin(),v.end());
	v.erase(unique(v.begin(),v.end()),v.end());
}

int get_id(int x)
{
	return lower_bound(v.begin(),v.end(),x)-v.begin()+1;
}
/*离散化*/

int main()
{
#ifndef ONLINE_JUDGE
//  freopen("input.txt","r",stdin);
//  freopen("output.txt","w",stdout);
#endif
//  ios::sync_with_stdio(false);
	int n,m,X,P;
	while(scanf("%d%d%d%d",&n,&m,&X,&P)!=EOF)
	{
		init(); 
		for(int i=1;i<=X+1;i++)
			node[i].clear();
		for(int i=1;i<=n;i++)
		{
			int l,r,d;
			scanf("%d%d%d",&l,&r,&d);
			node[l].push_back(d);
			node[r+1].push_back(-d);
			v.push_back(d);
		}
		discreate();
		for(int i=1;i<=X;i++)
		{
			root[i]=root[i-1];
			for(auto t:node[i])
				update(get_id(abs(t)),t<0?-1:1,root[i],1,v.size());
		}
		LL pre=1;
		while(m--)
		{
			int x,a,b,c;
			scanf("%d%d%d%d",&x,&a,&b,&c);
			int k=(pre*a+b)%c;
			LL ans=query(root[x],k,1,v.size());
			if(pre>P)
				ans*=2;
			printf("%lld\n",ans);
			pre=ans;
		}
	}
















    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_45458915/article/details/106866910