CodeForces 1321 E.World of Darkraft: Battle for Azathoth (segment tree)

Meaning of the questions:

There are n number of weapons, each weapon attack and take
with m armor, each anti-defense and has spent
a p monsters, each monster attack and defense, and gold
and now you have to buy weapons and armor each a, if assault weapons is strictly greater than monsters, armor and defense strictly greater than the monster, you can kill monsters
to ask how much is maximum profit, revenue equals monster drops gold minus the cost of weapons and armor

Ideas:

If the press is easy to find weapons to attack from small to large, then the enumeration weapon, and kill the monster number is monotonous, armor empathy.
Weapons, monster Sort by ordering the attack, armor sorted by defense, both from small to large.
Establish tree line, set up a (i) for the selection of the i-th armor gains, initialized to spend armor
then enumerate the weapon of choice for each weapon, kill the monster only become more
for the extra half monster that can beat this monster's armor interval, the interval Jia Fajia with the tree line on the line,
because you want to calculate the maximum income, plus a range of one of the most value on the line.

ps: This problem will tle with cin

code:

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxm=2e5+5;
struct Node{
    int a,c;
    bool operator<(Node x){
        return a<x.a;
    }
}x[maxm],y[maxm];
struct Node2{
    int a,b,c;
    bool operator<(Node2 x){
        return a<x.a;
    }
}z[maxm];
int a[maxm<<2];
int laz[maxm<<2];
void pushup(int node){
    a[node]=max(a[node*2],a[node*2+1]);
}
void pushdown(int node){
    if(laz[node]){
        a[node*2]+=laz[node];
        a[node*2+1]+=laz[node];
        laz[node*2]+=laz[node];
        laz[node*2+1]+=laz[node];
        laz[node]=0;
    }
}
void build(int l,int r,int node){
    laz[node]=0;
    if(l==r){
        a[node]=-y[l].c;
        return ;
    }
    int mid=(l+r)/2;
    build(l,mid,node*2);
    build(mid+1,r,node*2+1);
    pushup(node);
}
void update(int st,int ed,int val,int l,int r,int node){
    if(st<=l&&ed>=r){
        laz[node]+=val;
        a[node]+=val;
        return ;
    }
    pushdown(node);
    int mid=(l+r)/2;
    if(st<=mid)update(st,ed,val,l,mid,node*2);
    if(ed>mid)update(st,ed,val,mid+1,r,node*2+1);
    pushup(node);
}
signed main(){
    int n,m,p;
    cin>>n>>m>>p;
    for(int i=1;i<=n;i++){
        scanf("%lld%lld",&x[i].a,&x[i].c);
    }
    for(int i=1;i<=m;i++){
        scanf("%lld%lld",&y[i].a,&y[i].c);
    }
    for(int i=1;i<=p;i++){
        scanf("%lld%lld%lld",&z[i].a,&z[i].b,&z[i].c);
    }
    sort(x+1,x+1+n);
    sort(y+1,y+1+m);
    sort(z+1,z+1+p);
    build(1,m,1);
    int ans=-1e18;//因为答案可能是负数,所以初始化为-inf
    int k=1;
    for(int i=1;i<=n;i++){
        while(k<=p&&x[i].a>z[k].a){//把当前武器可以击败的加进线段树
            int l=1,r=m;
            int st=-1;
            while(l<=r){//二分找出需要加的区间左端点
                int mid=(l+r)/2;
                if(z[k].b<y[mid].a){
                    st=mid;
                    r=mid-1;
                }else{
                    l=mid+1;
                }
            }
            if(st!=-1)update(st,m,z[k].c,1,m,1);
            k++;
        }
        ans=max(ans,a[1]-x[i].c);
    }
    cout<<ans<<endl;
    return 0;
}
Published 430 original articles · won praise 36 · views 20000 +

Guess you like

Origin blog.csdn.net/weixin_44178736/article/details/104635815