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


    传送门

    题意

    (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_{1le ile n,1le jle 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;
    }
    
  • 相关阅读:
    keeprunning1的使用说明
    团队冲刺第十五天
    团队冲刺第十四天
    团队第一阶段冲刺评价
    团队第一阶段成果展示
    团队冲刺第十三天
    团队冲刺第十二天
    团队冲刺第十一天
    团队冲刺第十天
    团队冲刺第九天
  • 原文地址:https://www.cnblogs.com/BakaCirno/p/12409119.html
Copyright © 2020-2023  润新知