題目鏈接:https://codeforces.com/contest/1321/problem/E
題目大意:
有n個武器。每個有屬性攻擊力:a[i],價格:ca[i]。
有m個盾牌。每個有屬性防禦力:b[i],價格:bc[i]。
有k個怪物。每個有防禦力xk, 攻擊力yk,價值zk。
現在你必須並且只能買一個武器和一個盾牌。如果你的攻擊力>怪物的防禦力並且你的防禦力>怪物的攻擊力。那麼你就可以打敗這隻怪物並且得到這隻怪物價值的錢。所以你的收益爲所有擊敗怪物的價值和-購買武器和盾牌的錢。現在讓你最大化收益。
思路:我們枚舉武器攻擊力a[i]。那麼我們可以打敗的怪物只可能是x[i]<a[i]。我們我們把以盾牌的防禦力y[i]爲軸建立線段樹。我們先把所有盾牌加入線段樹。值爲(-價格)。
那麼我們在枚舉a[i]時把所有x[i]<a[i]的怪物加入線段樹。(b[i], k)。那麼線段樹就可以logn查詢到現在的買當前武器,買任意盾牌可以收益的最大值。
線段樹維護:sum爲怪物得到價格前綴和,mx爲買當前區間盾牌可能收益的最大值。分別維護就可以了
#include<bits/stdc++.h>
#define LL long long
#define mid (l+r)/2
using namespace std;
struct ode{
int x, y;
}a[200005];
struct gw{
int x, y, z;
}c[200005];
struct Node{
LL l, r;
LL sum, mx, pos;
}node[5000000];
void BT(LL i, LL l, LL r){
node[i].l=l;
node[i].r=r;
if(l==r){
node[i].mx=node[i].sum=node[i].pos=0;
return ;
}
BT(i<<1, l, mid);
BT((i<<1)+1, mid+1, r);
}
void GX(LL i, LL x, LL y, LL z){
if(node[i].l==node[i].r){
if(z==0){
node[i].sum+=y;
}
else{
if(node[i].pos==0){
node[i].mx=y;
node[i].pos=1;
}
else{
node[i].mx=max(node[i].mx, y);
node[i].pos=1;
}
}
return ;
}
if(x<=(node[i].l+node[i].r)/2){
GX(i<<1, x, y, z);
}
else{
GX((i<<1)+1, x, y, z);
}
if(node[i<<1].pos&&node[(i<<1)+1].pos){
node[i].mx=max(node[i<<1].mx, node[(i<<1)+1].mx+node[i<<1].sum);
node[i].pos=1;
}
else if(node[i<<1].pos){
node[i].mx=node[i<<1].mx;
node[i].pos=1;
}
else if(node[(i<<1)+1].pos){
node[i].mx=node[(i<<1)+1].mx+node[i<<1].sum;
node[i].pos=1;
}
node[i].sum=node[i<<1].sum+node[(i<<1)+1].sum;
}
LL CX(){
return node[1].mx;
}
int cmp(ode a, ode b){
return a.x<b.x;
}
int main(){
int n, m, k, x, y, z, tot=1;
scanf("%d%d%d",&n, &m, &k);
for(int i=1; i<=n; i++){
scanf("%d%d", &a[i].x, &a[i].y);
}
sort(a+1, a+1+n, cmp);
BT(1, 1, 1e6);
for(int i=1; i<=m; i++){
scanf("%d%d", &x, &y);
GX(1, x, -y, 1);
}
for(int i=1; i<=k; i++){
scanf("%d%d%d", &c[i].x, &c[i].y, &c[i].z);
}
LL mx=-(1ll<<60);
sort(c+1, c+k+1, [](gw &a, gw &b){return a.x<b.x;});
for(int i=1; i<=n; i++){
while(tot<=k&&c[tot].x<a[i].x){
GX(1, c[tot].y, c[tot].z, 0);
tot++;
}
LL ans=CX();
mx=max(mx, ans-a[i].y);
}
printf("%lld\n", mx);
return 0;
}