Shooting HDU - 4866 主席樹+思維

In the shooting game, the player can choose to stand in the position of [1, X] to shoot, you can shoot all the nearest K targets. The value of K may be different on different shootings. There are N targets to shoot, each target occupy the position of [Li, Ri] , the distance from the starting line is Di(1<=i<=N). Shooting a target can get the bonus points equal to the distance to the starting line. After each shooting targets still exist. Additional, if the previous bonus points is more than P, then as a reward for the shooting present bonus points doubled(and then check the next one). Player wants to know the bonus points he got in each shot. 

Input

The input consists several test cases. 
The first line has two integers, N, M, X, P(1<=N, M ,X<=100000, P<=1000000000), N represents the total number of target shooting, M represents the number of shooting.
The next N lines of three integers L, R, D (1<=L<=R<=X, 1<=D<=10000000), occupy the position of [L, R] and the distance from the starting line is D. 
The next M lines, each line contains four integers x, a, b, c (1<=x<=X, 0<=a,b<=N, 1<=c<=10000000), and K = ( a * Pre + b ) % c. Pre is the bonus point of previous shooting , and for the first shooting Pre=1. It denotes standing in the position x and the player can shoot the nearest K targets.

Output

Output M lines each corresponds to one integer.

Sample Input

4 3 5 8
1 2 6
2 3 3
2 4 7
1 5 2
2 2 1 5
3 1 1 10
4 2 3 7

Sample Output

11
10
18

題意:給你n,m,X,p。n表示有n個線段,m表示有m次詢問。接下來n行,每行有3個數l,r,d,表示線段的左端點右端點以及線段的高度。接下來m行,每行4個數x,a,b,c,k=(lastans*a+b)%c,表示你從x這個點向上開槍,能擊穿k條線段,每擊穿一條線段,你獲得的價值爲該線段的高度。如果該點上面的線段小於k,其上線段條數爲x,那麼獲得的總價值爲x條線段的價值加上x上面最高的線段的高度*(k-x)。並且,如果lastans>p,那麼本次開槍獲得的價值講翻倍。輸出每次開槍的獲得的價值。

思路:能擊穿的k條線段,一定是x向上的前k高的線段,這時我們很容易想到主席樹求區間前k小的值,很容易聯想到主席樹。那麼主席樹就維護高度,由於高度最大是1e7,因此我們需要進行離散化。那麼我們怎麼向主席樹裏插入這些線段呢?我們可以將一個線段拆成2個點:l和r+1,類似於差分的思想,在l處+1,在r+1處-1,按位置從小到大排序,依次插入到主席樹中。我們再記錄一個cnt,表示現在主席樹中有幾條線段,二分找前k個即可。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e6+100;
int n,m,X,l,r,d,cnt,cont,ct,x,k;
int root[maxn],b[maxn];
ll p,pre,ans,A,B,C;
struct node{
	int pos;
	int d;
	int flag;
	friend bool operator < (node x,node y)
	{
		if(x.pos==y.pos) return x.d<y.d;
		else return x.pos<y.pos;
	}
}a[maxn<<1];
struct Node{
	int l;
	int r;
	ll sum;
	int cnt;
}tree[maxn*40];
int getid(int x)
{
	return lower_bound(b+1,b+1+cont,x)-b;
}
void build(int &cur,int l,int r)
{
	cur=++ct;
	tree[cur].sum=0;
	tree[cur].cnt=0;
	if(l==r) return ;
	int m=(l+r)>>1;
	build(tree[cur].l,l,m);
	build(tree[cur].r,m+1,r);
}
void update(int &now,int last,int tar,int flag,ll val,int l,int r)
{
	now=++ct;
	tree[now]=tree[last];
	tree[now].sum+=flag*val;
	tree[now].cnt+=flag;
	if(l==r) return ;
	int m=(l+r)>>1;
	if(tar<=m) update(tree[now].l,tree[last].l,tar,flag,val,l,m);
	else update(tree[now].r,tree[last].r,tar,flag,val,m+1,r);
}
ll query(int cur,int k,int l,int r)
{
	if(tree[cur].cnt<=k) return tree[cur].sum;
	if(l==r) return (ll)(tree[cur].sum/tree[cur].cnt)*k;
	int m=(l+r)>>1;
	if(tree[tree[cur].l].cnt>=k) return query(tree[cur].l,k,l,m);
	else return tree[tree[cur].l].sum+query(tree[cur].r,k-tree[tree[cur].l].cnt,m+1,r); 
}
int main()
{
	while(~scanf("%d%d%d%lld",&n,&m,&X,&p))
	{
		cnt=0;pre=1;ct=0;
		for(int i=1;i<=n;i++)
		{
			scanf("%d%d%d",&l,&r,&d);
			a[++cnt].pos=l;
			a[cnt].d=d;
			a[cnt].flag=1;
			a[++cnt].pos=r+1;
			a[cnt].d=d;
			a[cnt].flag=-1;
			b[i]=d;
		}
		sort(b+1,b+1+n);
		sort(a+1,a+1+cnt);
		cont=unique(b+1,b+1+n)-(b+1);
		build(root[0],1,cont);
		for(int i=1;i<=cnt;i++) update(root[i],root[i-1],getid(a[i].d),a[i].flag,a[i].d,1,cont);
		while(m--)
		{
			scanf("%d%lld%lld%lld",&x,&A,&B,&C);
			k=((A*pre)%C+B)%C;
			node tmp;
			tmp.pos=x;tmp.flag=0;tmp.d=0x3fffffff;
			int id=upper_bound(a+1,a+1+cnt,tmp)-a-1;
			if(id<=0) ans=0;
			else ans=query(root[id],k,1,cont);
			if(pre>p) ans*=2;
			printf("%lld\n",ans);
			pre=ans;
		}
	}
	return 0;
}

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章