P12581 [UOI 2021] 敌人与军刀 题解
TimSwn090306 · · 题解
Description
初始有
数据范围:
Solution
把军刀和敌人放到二维平面上,对于选定的若干军刀,有贡献的敌人呈阶梯状(如下图)。
将所有点按
注意到计算
发现
仍是从下到上枚举纵坐标
尝试维护
时间复杂度
Code
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=2e6+5;
const ll INF=1e16;
int n,m,tot,b[maxn];
struct node{
int type,x,y,c;
inline bool operator < (node tmp) const{
if (y!=tmp.y) return y<tmp.y;
if (x!=tmp.x) return x<tmp.x;
if (type!=tmp.type) return type<tmp.type;
return c<tmp.c;
}
}s[maxn];
namespace SGT{
#define lc(rt) ((rt)<<1)
#define rc(rt) ((rt)<<1|1)
const int maxc=(maxn<<2);
ll add[maxc],getmax[maxc];
inline void lazy_add(int rt,ll k){
add[rt]+=k;
}
inline void lazy_max(int rt,ll k){
getmax[rt]=max(getmax[rt],k-add[rt]);
}
inline void pushdown(int rt){
if (getmax[rt]){
lazy_max(lc(rt),getmax[rt]);
lazy_max(rc(rt),getmax[rt]);
getmax[rt]=0;
}
if (add[rt]){
lazy_add(lc(rt),add[rt]);
lazy_add(rc(rt),add[rt]);
add[rt]=0;
}
}
inline void update_add(int rt,int l,int r,int ql,int qr,ll k){
if (l>=ql && r<=qr){
lazy_add(rt,k);
return ;
}
pushdown(rt);
int mid=(l+r)>>1;
if (ql<=mid) update_add(lc(rt),l,mid,ql,qr,k);
if (qr>mid) update_add(rc(rt),mid+1,r,ql,qr,k);
}
inline void update_max(int rt,int l,int r,int ql,int qr,ll k){
if (l>=ql && r<=qr){
lazy_max(rt,k);
return ;
}
pushdown(rt);
int mid=(l+r)>>1;
if (ql<=mid) update_max(lc(rt),l,mid,ql,qr,k);
if (qr>mid) update_max(rc(rt),mid+1,r,ql,qr,k);
}
inline ll query(int rt,int l,int r,int p){
if (l==r){
return max(0ll,getmax[rt])+add[rt];
}
pushdown(rt);
int mid=(l+r)>>1;
if (p<=mid) return query(lc(rt),l,mid,p);
else return query(rc(rt),mid+1,r,p);
}
}
ll f[maxn];
inline int rd(){
int x=0; char ch=getchar();
while (ch<'0' || ch>'9') ch=getchar();
while (ch>='0' && ch<='9'){
x=(x<<3)+(x<<1)+(ch-'0');
ch=getchar();
}
return x;
}
int main(){
n=rd(),m=rd();
for (int i=1;i<=n;i++) s[i].x=rd(),s[i].y=rd(),s[i].c=rd(),s[i].type=-1;
for (int i=1;i<=m;i++) s[i+n].x=rd(),s[i+n].y=rd(),s[i+n].c=rd(),s[i+n].type=+1;
for (int i=1;i<=n+m;i++) b[++tot]=s[i].x;
sort(b+1,b+tot+1);
tot=unique(b+1,b+tot+1)-b-1;
for (int i=1;i<=n+m;i++) s[i].x=lower_bound(b+1,b+tot+1,s[i].x)-b;
sort(s+1,s+n+m+1);
memset(SGT::getmax,-0x3f,sizeof(SGT::getmax));
for (int i=1;i<=n+m;i++){
int j=i;
while (j<=n+m && s[j].y==s[i].y) j++;
for (int k=i;k<j;k++){
if (s[k].type==+1){
SGT::update_add(1,1,tot,s[k].x,tot,s[k].c);
}
}
ll maxx=-INF;
for (int k=i;k<j;k++){
if (s[k].type==-1){
f[k]=SGT::query(1,1,tot,s[k].x)-s[k].c;
maxx=max(maxx,f[k]);
}
}
SGT::update_max(1,1,tot,1,tot,maxx);
i=j-1;
}
ll ans=-INF;
for (int i=1;i<=n+m;i++) ans=max(ans,f[i]);
printf("%lld\n",ans);
return 0;
}