码迷,mamicode.com
首页 > 其他好文 > 详细

CodeForces 1321E. World of Darkraft: Battle for Azathoth(线段树)

时间:2020-03-04 14:20:21      阅读:85      评论:0      收藏:0      [点我收藏+]

标签:tag   n+1   思维   ace   答案   second   ttl   turn   stream   

传送门

题意

\(a_1,a_2,...,a_n\)\(b_1,b_2,...,b_m\)\((x_1,y_1,w_1),(x_2,y_2,w_2),...,(x_p,y_p,w_p)\)

\[\max_{1\le i\le n,1\le j\le m}\{\sum_{x_k<a_i,y_k<b_j}w_k-a_i-b_j\}\]
其实就是分别选一个 \(a_i,b_j\),求矩形 \((0,0),(a_i,b_j)\) 内部的点的 \(w\) 总和减 \(a_i+b_j\) 的最大值

题解

这种偏序问题基本上都可以考虑用线段树解决
借助扫描线的思维,枚举 x 轴枚举,线段树维护 y 轴
沿着 x 轴依次将点值加入其 y 轴对应坐标,然后直接查询线段树中的最大值
这个线段树显然应该维护前缀和,这样我们的到的最大值就是前缀和的最大值
就是问题的答案了
当然最初时要将 \(b_j\) 从线段树上减去

代码

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
using namespace std;
typedef long long LL;
typedef pair<int,LL> PII;
const int inf=0x3f3f3f3f;
const LL INF=0x3f3f3f3f3f3f3f3f;
const int MAXN=2e5+10;
const int MAXM=1e6+10;
int n,m,p;
PII a[MAXN],b[MAXN],temp[MAXN];
struct Turp{
    int x,y,w;
}t[MAXN];
bool cmp(Turp a,Turp b){return a.x<b.x;}
struct SegTree{
    #define mid ((l+r)>>1)
    LL maxv[MAXM*4],tag[MAXM*4];
    void pushdown(int id){
        maxv[id<<1]+=tag[id];tag[id<<1]+=tag[id];
        maxv[id<<1|1]+=tag[id];tag[id<<1|1]+=tag[id];
        tag[id]=0;
    }
    void update(int id,int l,int r,int L,int R,LL x,int opt){
        if(L<=l&&r<=R)
            if(opt) {maxv[id]+=x;tag[id]+=x;return;}
            else {maxv[id]=max(maxv[id],x);return;}
        if(tag[id]) pushdown(id);
        if(L<=mid) update(id<<1,l,mid,L,R,x,opt);
        if(R>mid) update(id<<1|1,mid+1,r,L,R,x,opt);
        maxv[id]=max(maxv[id<<1],maxv[id<<1|1]);
    }
    #undef mid
}tr;

int main(){
    scanf("%d%d%d",&n,&m,&p);
    for(int i=1;i<=n;i++) scanf("%d%d",&a[i].first,&a[i].second);
    for(int i=1;i<=m;i++) scanf("%d%d",&b[i].first,&b[i].second);
    for(int i=1;i<=p;i++) scanf("%d%d%d",&t[i].x,&t[i].y,&t[i].w);
    sort(a+1,a+n+1);
    sort(b+1,b+m+1);
    sort(t+1,t+p+1,cmp);
    memset(tr.maxv,0xc0,sizeof(tr.maxv));
    LL temp=-INF;
    for(int i=1e6,j=m;i>=0;i--){
        while(i<b[j].first) temp=max(temp,-b[j].second),j--;
        tr.update(1,0,1e6,i,i,temp,0);
    }
    LL ans=-INF;
    for(int i=1,j=1;i<=n;i++){
        while(j<=p&&t[j].x<a[i].first) tr.update(1,0,1e6,t[j].y,1e6,t[j].w,1),j++;
        ans=max(ans,tr.maxv[1]-a[i].second);
    }
    cout<<ans<<endl;
    return 0;
}

CodeForces 1321E. World of Darkraft: Battle for Azathoth(线段树)

标签:tag   n+1   思维   ace   答案   second   ttl   turn   stream   

原文地址:https://www.cnblogs.com/BakaCirno/p/12409119.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!