线段树
又是熟悉的感觉,又是E题写完了,没调完,不过还好上了紫
可以发现可以打败怪兽的关系类似二维偏序
那么首先考虑第一维(武器)以攻击值($a_{i}$)进行排序
把所有的怪兽以防御力($x_{i}$)进行排序
然后用双指针维护到目前遍历到的武器,可以打败的怪兽
然后考虑防具和怪兽的攻击力也就是第二维
首先先定义$lb$数组,$lb[i]$表示所选防具至少为$i$的最少花费
可以用差分求出
可以发现如果选到防御力为$i$的防具,那么所有当前可以打败的怪兽中,只要攻击力小于$i$都可以累加到答案中
那么考虑$mx[i]$表示维护防御力最大为$i$的最大获利(包含防具的开支,武器的开支在最后计算)
对于一只新增的怪兽只要$i$大于其防御力,那么$mx[i]$都可以加上这只怪兽的获利
线段树维护即可
还要注意武器和防具里必选,不能不选
1 #include <bits/stdc++.h> 2 #define inf 1e18 3 #define int long long 4 using namespace std; 5 const int N=2*1e5+100,NUM=1e6+100; 6 int n,m,p,lb[NUM],ans,mb; 7 struct tool 8 { 9 int f,cost; 10 }; 11 tool a[N],b[N]; 12 struct monsters 13 { 14 int x,y,z; 15 }c[N]; 16 struct node 17 { 18 int MAX,lazy; 19 }sh[NUM*4]; 20 bool cmp(tool a,tool b) 21 { 22 return a.f<b.f; 23 } 24 bool cmp1(monsters a,monsters b) 25 { 26 return a.x<b.x; 27 } 28 void pushup(int x) 29 { 30 sh[x].MAX=max(sh[x+x].MAX,sh[x+x+1].MAX); 31 } 32 void pushdown(int x) 33 { 34 if (sh[x].lazy!=0) 35 { 36 sh[x+x].lazy+=sh[x].lazy; 37 sh[x+x+1].lazy+=sh[x].lazy; 38 sh[x+x].MAX+=sh[x].lazy; 39 sh[x+x+1].MAX+=sh[x].lazy; 40 sh[x].lazy=0; 41 } 42 } 43 void build(int x,int l,int r) 44 { 45 if (l==r) 46 { 47 sh[x].MAX=-lb[l];//处理当前防具的价格 48 return; 49 } 50 int mid=(l+r)>>1; 51 build(x+x,l,mid); 52 build(x+x+1,mid+1,r); 53 pushup(x); 54 } 55 void change(int x,int l,int r,int ll,int rr,int v)//区间修改 56 { 57 if (ll<=l && r<=rr) 58 { 59 sh[x].MAX+=v; 60 sh[x].lazy+=v; 61 return; 62 } 63 int mid=(l+r)>>1; 64 pushdown(x); 65 if (ll<=mid) change(x+x,l,mid,ll,rr,v); 66 if (rr>mid) change(x+x+1,mid+1,r,ll,rr,v); 67 pushup(x); 68 } 69 signed main() 70 { 71 scanf("%lld%lld%lld",&n,&m,&p); 72 for (int i=1;i<=n;i++) scanf("%lld%lld",&a[i].f,&a[i].cost); 73 for (int i=1;i<=m;i++) scanf("%lld%lld",&b[i].f,&b[i].cost); 74 for (int i=1;i<=p;i++) scanf("%lld%lld%lld",&c[i].x,&c[i].y,&c[i].z); 75 sort(a+1,a+1+n,cmp); 76 sort(c+1,c+1+p,cmp1); 77 for (int i=1;i<=m;i++) mb=max(mb,b[i].f); 78 for (int i=1;i<=mb;i++) lb[i]=inf; 79 for (int i=1;i<=m;i++) lb[b[i].f]=min(lb[b[i].f],b[i].cost); 80 for (int i=mb-1;i>=1;i--) lb[i]=min(lb[i+1],lb[i]);//差分求出lb数组 81 ans=-inf; 82 build(1,1,mb); 83 for (int i=1,j=1;i<=n;i++) 84 { 85 while (c[j].x<a[i].f && j<=p)//双指针维护当前可以击败的怪兽 86 { 87 if (c[j].y+1<=mb)//在防御力最大的防具之内 88 change(1,1,mb,c[j].y+1,mb,c[j].z);//要严格大于 89 j++; 90 } 91 ans=max(ans,-a[i].cost+sh[1].MAX);//最后计算武器的代价 92 } 93 printf("%lld ",ans); 94 }