题意:在一个射击游戏里面,游戏者可以选择地面上【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; }