hdu4866(可持久化线段树)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_25576697/article/details/82013422

Shooting

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 2777    Accepted Submission(s): 638

Problem Description

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

 

题意:在二维空间中有一些平行于x轴的线段,现在有m次,每次在x轴上一个点去垂直x轴射击他们,每次只能射击邻近的k个线段,k可由题中公式算出,射击每个线段的得分为它到x轴距离,且射击后下一次射击那条线段还在,每次射击分数大于p,下一次射击的分数会变双倍。问每一次射击所得分数。

思路:根据线段到x轴的距离建主席树(需要hash一下),扫描线,x从左往右扫描,没扫描到一个线段的左端点,插入主席树,相应距离的cnt和val++,遇到右端点则相应的cnt和val--,查询的时候,二分到对应的root,查询前k个的val和。

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<map>
using namespace std;
typedef long long ll;
const int maxn = 100010;
const int inf = 0x3fffffff;
int n,m,X;
ll p;
struct pnode
{
    int flag;
    int d;
    int x;
    bool operator < (const pnode &b) const 
    {
        if(x!=b.x)return x<b.x;
        if(d!=b.d)return d<b.d;
        return x<b.x;    
    }
}tag_point[maxn<<1];
int dis[maxn];
map<int,bool>mp;
struct  node
{
    int chl,chr;
    int cnt;
    ll val;
}t[maxn*35];
int root[maxn<<2];
int tot = 0;
void build(int &x,int l,int r) {
    x=++tot;
    t[x].cnt = 0;
    t[x].val = 0;   
    if (l==r) return ;
    int mid=(l+r)>>1;
    build(t[x].chl,l,mid); build(t[x].chr,mid+1,r);
}
void insert(int &x,int rot,int key,int flag,ll val,int l,int r) 
{
    x=++tot;
    t[x].chl=t[rot].chl;
    t[x].chr=t[rot].chr;
    t[x].cnt=t[rot].cnt+flag;
    t[x].val=t[rot].val + flag*val;
    if (l==r) {
        return ;
    }
    int mid=(l+r)>>1;
    if (key>mid) {
        insert(t[x].chr,t[rot].chr,key,flag,val,mid+1,r);
    } else {
        insert(t[x].chl,t[rot].chl,key,flag,val,l,mid);
    }
}
ll query(int a,int l,int r,int k)
{
    if(t[a].cnt<=k)return t[a].val;
    if(l==r)
    {
        if(t[a].cnt>k)
        {
            return (ll)(t[a].val/t[a].cnt)*k;
        }
        else return 0;
    }
    int mid = (l+r)>>1;
    if(k<=t[t[a].chl].cnt)return query(t[a].chl,l,mid,k);
    else  
    {
        return t[t[a].chl].val + query(t[a].chr,mid+1,r,k - t[t[a].chl].cnt);
    }
}
int main()
{
    while(~scanf("%d%d%d%lld",&n,&m,&X,&p))
    {
        mp.clear();
        int l,r,d;
        int cnt = 0;
        int cntd = 0;
        for(int i = 0;i<n;i++)
        {
            scanf("%d%d%d",&l,&r,&d);
            r++;
            if(!mp[d])
            {
                mp[d] = 1;
                dis[cntd++] = d;
            }
            tag_point[cnt].x = l;
            tag_point[cnt].d = d;
            tag_point[cnt++].flag = 1;
            tag_point[cnt].x = r;
            tag_point[cnt].d = d;
            tag_point[cnt++].flag = -1;
        }
        sort(tag_point,tag_point+cnt);
        sort(dis,dis+cntd);
        tot = 0;
        build(root[0],1,cntd);
        for(int i = 0;i<cnt;i++)
        {
            int hash_d = lower_bound(dis,dis+cntd,tag_point[i].d)-dis+1;
            insert(root[i+1],root[i],hash_d,tag_point[i].flag,tag_point[i].d,1,cntd);
        }
        int x;
        ll a,b,c;
        ll pre = 1;
        int k;
        ll ans;
        while(m--)
        {
            scanf("%d%lld%lld%lld",&x,&a,&b,&c);
            k = ((a*pre)%c+b)%c;
            if(!k)ans = 0;
            else
            {
                pnode tmp;
                tmp.x = x;
                tmp.d = inf;
                tmp.flag = 0;
                int id = upper_bound(tag_point,tag_point+cnt,tmp) - tag_point;
                if(id==0)ans = 0;
                else ans = query(root[id],1,cntd,k);
            }
            if(pre>p)ans*=2;
            printf("%lld\n",ans);
            pre = ans;
        }
    }
}   

猜你喜欢

转载自blog.csdn.net/qq_25576697/article/details/82013422