CodeForces 1321 E.World de Darkraft: Bataille pour Azathoth (arbre de segment)

Signification des questions:

Il y a n nombre d'armes, chaque attaque d'armes et de prendre
avec m armure, chaque anti-défense et a passé
un monstres p, chaque attaque de monstre et de la défense, et de l' or
et maintenant vous devez acheter des armes et armures chaque a, si des armes d'assaut est strictement supérieur à des monstres, l' armure et de la défense strictement plus grand que le monstre, vous pouvez tuer des monstres
pour demander combien est le profit maximum, le revenu est égal monstre gouttes d' or moins le coût des armes et armures

idées:

Si la presse est facile de trouver des armes pour attaquer de petite à grande, l'arme de l' énumération, et tuer le nombre de monstre est monotone, l' empathie d'armure.
Armes, monstre Trier en ordonnant l'attaque, l' armure triées par la défense, à la fois de petite à grande.
Mettre en place la ligne d'arbre, mettre en place un (i) pour la sélection des i-ième gains d'armure, initialisé à passer une armure
puis énumérer l'arme de choix pour chaque arme, tuez le monstre ne devenir plus
pour la moitié supplémentaire monstre qui peut battre ce intervalle d'armure de monstre, l'intervalle Jia Fajia avec la ligne d'arbre sur la ligne,
parce que vous voulez calculer le revenu maximum, ainsi qu'une gamme de l' un des plus de valeur sur la ligne.

ps: Ce problème TLE avec 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;
}
Publié 430 articles originaux · a gagné les éloges 36 · vues 20000 +

Je suppose que tu aimes

Origine blog.csdn.net/weixin_44178736/article/details/104635815
conseillé
Classement