E. World of Darkraft: Battle for Azathoth
阿新 • • 發佈:2020-07-24
E. World of Darkraft: Battle for Azathoth
題目大意:
給你n個武器和m個防禦,每一個武器有一個攻擊值 a 和這個武器的價格,每一個防禦有一個防禦值b和這個防禦的價格,有p個怪物,每一個怪物有一個防禦值x攻擊值y,和打贏這個怪物收穫的價值z。
你買一個武器和一個防禦,問最大的利潤是多少(收穫的價值減去花費),必須選一個武器和一個防禦。
題解:
開始我以為這個題目是一個優先佇列,然後發現不對。
其實cf上一般有 \(data \,srtuctures\) 這個標籤的都是線段樹。
而且一般cf上2000左右的線段樹都比較簡單,也不是說特別簡單,就是可以自己想到的,而且套路就那麼幾種,基本上都是離線+排序,通過求差值放到線段樹裡面來維護,通過更新區間來更新點。。。
其實也不太記得了,以後有時間可以整理一下。
接下來正式說說這個題目的解析:
首先這個有三個值,一個是武器,一個是防禦,一個是怪物。
首先對武器和防禦進行排序,然後對怪物按照防禦值進行排序,之後遍歷武器,對於每一個攻擊值a,找到武力值小於a的所有怪物,這個時候我怎麼判斷要哪個防禦呢?也許你說可以二分,那麼是不是每一個怪物都要二分一次?以後每次放入一個滿足條件的怪物,是不是都需要對每一個怪物二分一次?那麼這個複雜度很明顯是過不了的,所以這個是需要我遍歷到武器 $i $ 的時候就馬上判斷出這個武器最好和哪一個防禦進行匹配,或者說和和一個防禦進行匹配之後的最大利潤。
這個地方就要用到線段樹了,首先把所有的防禦的位置的賦值成這個花費的負數,其他位置賦值為-inf,然後每次放入一個怪物,這個怪物的攻擊值是y,就直接更新區間 \([y+1,end]\)
#include <bits/stdc++.h> #define inf 0x3f3f3f3f #define inf64 0x3f3f3f3f3f3f3f3f using namespace std; typedef long long ll; const int maxn= 1e6+10; const int M = 1e6+2; struct node{ int x,y,w; node(int x=0,int y=0,int w=0):x(x),y(y),w(w){} }a[maxn],b[maxn]; ll maxs[maxn<<2],lazy[maxn<<2]; bool cmp(node a,node b){ return a.x<b.x; } void push_up(int id){ maxs[id]=max(maxs[id<<1],maxs[id<<1|1]); } void modify(int id,int l,int r,int pos,ll w){ if(l==r){ maxs[id]=max(maxs[id],w); return ; } int mid=(l+r)>>1; if(pos<=mid) modify(id<<1,l,mid,pos,w); else modify(id<<1|1,mid+1,r,pos,w); push_up(id); } void push_down(int id) { if (!lazy[id]) return; lazy[id << 1] += lazy[id]; lazy[id << 1 | 1] += lazy[id]; maxs[id << 1] += lazy[id]; maxs[id << 1 | 1] += lazy[id]; lazy[id] = 0; } void update(int id,int l,int r,int x,int y,int val) { if (x <= l && y >= r) { lazy[id] += val; maxs[id] += val; return; } int mid = (l + r) >> 1; push_down(id); if (x <= mid) update(id << 1, l, mid, x, y, val); if (y > mid) update(id << 1 | 1, mid + 1, r, x, y, val); push_up(id); } int main(){ int n,m,p; scanf("%d%d%d",&n,&m,&p); memset(maxs,0xef,sizeof(maxs)); for(int i=1;i<=n;i++){ int x,w; scanf("%d%d",&x,&w); a[i]=node(x,0,w); } sort(a+1,a+1+n,cmp); for(int i=1;i<=m;i++){ int x,w; scanf("%d%d",&x,&w); modify(1,1,M,x,-w); } for(int i=1;i<=p;i++){ int x,y,w; scanf("%d%d%d",&x,&y,&w); b[i]=node(x,y,w); } sort(b+1,b+1+p,cmp); int now = 1; ll ans = -inf64; for(int i=1;i<=n;i++){ while(now<=p&&b[now].x<a[i].x){ update(1,1,M,b[now].y+1,M,b[now].w); now++; } ans = max(ans,maxs[1]-a[i].w); // printf("i=%d now=%d x=%d w=%d maxs=%d\n",i,now,a[i].x,a[i].w,maxs[1]); } printf("%lld\n",ans); return 0; }