• HDU 4866 Shooting(主席树)题解


    题意:在一个射击游戏里面,游戏者可以选择地面上【1,X】的一个点射击,并且可以在这个点垂直向上射击最近的K个目标,每个目标有一个价值,价值等于它到地面的距离。游戏中有N个目标,每个目标从L覆盖到R,距离地面高度D。每次射击一个目标可以得到目标价值大小的分数,每次射击以后目标不会消失。如果在该点上方的目标个数小于可以射击的次数,那么就当多出来的次数全部射在该点上方最高的目标身上。如果上一个询问 > p,那么本次总得分翻倍。

    思路:简单的主席树模板题。区间覆盖直接L上+1,R+1上-1就行了。然后搞一下区间和,区间数量。

    代码:

    #include<cmath>
    #include<set>
    #include<map>
    #include<queue>
    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include <iostream>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    const int maxn = 1e5 + 10;
    const int M = maxn * 30;
    const ull seed = 131;
    const int INF = 0x3f3f3f3f;
    const int MOD = 1e4 + 7;
    int n, q, tot;
    int root[maxn];
    vector<ll> vv;
    int getId(int x){
        return lower_bound(vv.begin(), vv.end(), x) - vv.begin() + 1;
    }
    struct node{
        int lson, rson;
        int num;
        ll sum;
    }T[maxn * 50];
    void update(int l, int r, int &now, int pre, int v, int pos){
        T[++tot] = T[pre], T[tot].num += v, T[tot].sum += v * vv[pos - 1], now = tot;
        if(l == r) return;
        int m = (l + r) >> 1;
        if(m >= pos)
            update(l, m, T[now].lson, T[pre].lson, v, pos);
        else
            update(m + 1, r, T[now].rson, T[pre].rson, v, pos);
    }
    ll query(int l, int r, int now, int k){
        if(l == r){
            return vv[l - 1] * k;
        }
        int m = (l + r) >> 1;
        int num = T[T[now].lson].num;
        ll sum = T[T[now].lson].sum;
        if(num >= k)
            return query(l, m, T[now].lson, k);
        else
            return sum + query(m + 1, r, T[now].rson, k - num);
    }
    ll query_max(int l, int r, int now){
        if(l == r) return vv[l - 1];
        int m = (l + r) >> 1;
        int num = T[T[now].rson].num;
        if(num > 0)
            return query_max(1, vv.size(), T[now].rson);
        else
            return query_max(1, vv.size(), T[now].lson);
    }
    vector<int> g[maxn];
    int m, x;
    int main(){
        ll p;
        while(~scanf("%d%d%d%lld", &n, &m, &x, &p)){
            tot = 0;
            vv.clear();
            for(int i = 1; i <= x; i++) g[i].clear();
            for(int i = 1; i <= n; i++){
                int u, v;
                ll d;
                scanf("%d%d%lld", &u, &v, &d);
                g[u].push_back(d);
                if(v + 1 <= x) g[v + 1].push_back(-d);
                vv.push_back(d);
            }
            sort(vv.begin(), vv.end());
            vv.erase(unique(vv.begin(), vv.end()), vv.end());
    
            for(int i = 1; i <= x; i++){
                root[i] = root[i - 1];
                for(int j = 0; j < g[i].size(); j++){
                    ll v = g[i][j];
                    update(1, vv.size(), root[i], root[i], v < 0? -1 : 1, getId(abs(v)));
                }
            }
    
            ll pre = 1, ans;
            while(m--){
                ll xx, a, b, c, k;
                scanf("%lld%lld%lld%lld", &xx, &a, &b, &c);
                k = (a * pre + b) % c;
                if(k > T[root[xx]].num){
                    ans = T[root[xx]].sum + query_max(1, vv.size(), root[xx]) * (k - T[root[xx]].num);
                }
                else{
                    ans = query(1, vv.size(), root[xx], k);
                }
                if(pre > p) ans *= 2;
                printf("%lld
    ", ans);
                pre = ans;
            }
        }
        return 0;
    }
  • 相关阅读:
    Leetcode-645 Set Mismatch
    2017百度软研(C++)
    二叉树中任意两个节点的最近公共祖先
    不用加减乘除做加法
    一些leetcode算法题
    Leetcode 98. Validate Binary Search Tree
    C++ 通过ostringstream 实现任意类型转string
    Leetcode 215. Kth Largest Element in an Array
    382. Linked List Random Node
    一些基础函数的实现
  • 原文地址:https://www.cnblogs.com/KirinSB/p/10939977.html
Copyright © 2020-2023  润新知