CF1320C World of Darkraft: Battle for Azathoth

线段树

又是熟悉的感觉,又是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\n",ans);
94 }
View Code

猜你喜欢

转载自www.cnblogs.com/huangchenyan/p/12404663.html