• Shooting HDU


    题意:

      在一个射击游戏里面,游戏者可以选择地面上 ([1,X]) 的一个点射击,并且可以在这个点垂直向上射击最近的 (K) 个目标,每个目标有一个价值,价值等于它到地面的距离。游戏中有 (N) 个目标,每个目标从 (L)(R),距离地面高度 (D)。每次射击一个目标可以得到目标价值大小的分数,每次射击以后目标不会消失。如果你前一次游戏得到的分数如果大于 (P),那么这次你得到的分数就翻倍。
    数据范围:(1<=N, M ,X<=10^5, P<=10^9)

    分析:

    主席树。
      根据询问,可以发现是以地面坐标来进行询问的。因此,可以以地面坐标为时间轴,目标的高度为权值建立主席树。但由于询问的结果是可以射击到的目标的高度和,而不是查询区间第 (k) 小。因此,主席树要维护两个东西:1.每个高度的出现次数;2.区间的高度和。对于目标的范围,根据主席树前缀和的思想,在时间 (L) 相应的高度 (+1),在时间 (R+1) 相应的高度 (-1)。记录下每个时间点要进行的操作。
    注意:当查询时,由于同一个高度的目标可能有多个,但查询可能不需要全部,所以要减掉一部分。

    代码:

    #include <bits/stdc++.h>
    #define pb push_back
    using namespace std;
    typedef long long ll;
    typedef pair<int,ll>P;
    const int N=1e5+5;
    int d[N];
    vector<P>tar[N];
    int root[N],cnt;
    struct node
    {
        ll sum;
        int num,lson,rson;
    }sht[N*40];//N<<5会RE
    int get_pos(int h,int len)
    {
        return lower_bound(d+1,d+1+len,h)-d;
    }
    int build(int l,int r)
    {
        int t=++cnt;
        if(l==r)
        {
            sht[t].num=0;
            sht[t].sum=0;
            return t;
        }
        int mid=(l+r)>>1;
        sht[t].lson=build(l,mid);
        sht[t].rson=build(mid+1,r);
        sht[t].sum=sht[sht[t].lson].sum+sht[sht[t].rson].sum;
        sht[t].num=sht[sht[t].lson].num+sht[sht[t].rson].num;
        return t;
    }
    int update(int l,int r,int pos,ll val,int rt)
    {
        int t=++cnt;
        sht[t]=sht[rt];
        if(l==r)
        {
            sht[t].num+=val;
            sht[t].sum+=1LL*val*d[pos];
            return t;
        }
        int mid=(l+r)>>1;
        if(pos<=mid)
            sht[t].lson=update(l,mid,pos,val,sht[rt].lson);
        else
            sht[t].rson=update(mid+1,r,pos,val,sht[rt].rson);
        sht[t].sum=sht[sht[t].lson].sum+sht[sht[t].rson].sum;
        sht[t].num=sht[sht[t].lson].num+sht[sht[t].rson].num;
        return t;
    }
    P query(int l,int r,ll k,int rt)
    {
        if(l==r)
        {
            P tp=make_pair(l,sht[rt].num-k);
            return tp;
        }
        int tn=sht[sht[rt].lson].num;
        int mid=(l+r)>>1;
        if(tn>=k)
            return query(l,mid,k,sht[rt].lson);
        else
            return query(mid+1,r,k-tn,sht[rt].rson);
    }
    ll query2(int l,int r,int L,int R,int rt)
    {
        if(L<=l&&r<=R)
            return sht[rt].sum;
        int mid=(l+r)>>1;
        ll ans=0;
        if(L<=mid)
            ans+=query2(l,mid,L,R,sht[rt].lson);
        if(R>mid)
            ans+=query2(mid+1,r,L,R,sht[rt].rson);
        return ans;
    }
    int main()
    {
        int n,m,X,p,x,a,b,c;
        while(scanf("%d%d%d%d",&n,&m,&X,&p)!=EOF)
        {
            int l,r,h;
            cnt=0;
            for(int i=0;i<=X+1;i++)
                tar[i].clear();
            for(int i=1;i<=n;i++)
            {
                scanf("%d%d%d",&l,&r,&h);
                d[i]=h;
                tar[l].pb(make_pair(h,1*1LL));
                tar[r+1].pb(make_pair(h,-1*1LL));
            }
            sort(d+1,d+1+n);
            int len=unique(d+1,d+1+n)-d-1;
            int pos=1;
            root[0]=build(1,len);
            for(int i=1;i<=X;i++)
            {
                if(tar[i].size()==0)
                {
                    root[i]=root[i-1];
                    continue;
                }
                for(int j=0;j<tar[i].size();j++)
                {
                    P t=tar[i][j];
                    h=get_pos(t.first,len);
                    if(j==0)
                        root[i]=update(1,len,h,t.second,root[i-1]);
                    else
                        root[i]=update(1,len,h,t.second,root[i]);
                }
            }
            ll pre=1;
            while(m--)
            {
                scanf("%d%d%d%d",&x,&a,&b,&c);
                ll k=(a*pre+b)%c;
                P tp=query(1,len,k,root[x]);
                ll ans=query2(1,len,1,tp.first,root[x]);
                ans-=1LL*d[tp.first]*(max(tp.second,0*1LL));
                if(pre>p)
                    ans*=2;
                printf("%lld
    ",ans);
                pre=ans;
            }
        }
        return 0;
    }
    
    
  • 相关阅读:
    编写isNull isArray isFunction的方法
    JS中Null与Undefined的区别
    css中关于transform、transition、animate的区别
    js数组去重的方法
    深入理解 Javascript 面向对象编程(转)
    js 创建类和继承的几种方法
    一道面试题,想明白之后好像锤自己几下~~
    关于offsetTop offsetHeight clientHeight scrollHeight scrollTop的区别研究
    alt和title的用法区别
    C++的黑科技(深入探索C++对象模型)
  • 原文地址:https://www.cnblogs.com/1024-xzx/p/12671155.html
Copyright © 2020-2023  润新知