題目鏈結
考慮每個節點建乙個以騎士攻擊力為關鍵字的小根堆,從葉子節點向上掃瞄,每次彈堆至堆頂騎士攻擊力大於當前城池防禦力,可以採用左偏樹維護,
對於城池的攻擊力改變值,可以借用線段樹區間修改的懶標記思想,打上乘法及加法標記,每次涉及到改變堆結構的操作前下放標記即可。
稍微卡常之後可過
**
# include # include # define maxn 300005
struct edgee[maxn];
int hd[maxn], cnte;
struct heaphp[maxn];
struct knightkn[maxn];
struct cityct[maxn];
int death[maxn], destory[maxn];
templatevoid rd(t & x);
void adde(int u, int v);
void dfs(int now, int fa);
int merge(int x, int y);
void pushdown(int now);
void calc(int now, long long mul, long long pls);
// int find(int x);
int main()
for(int i = 2, tmp; i <= n; i++)
for(int i = 1; i <= m; i++)
dfs(1, 0);
while(hp[1].rt)
for(int i = 1; i <= n; i++)
for(int i = 1; i <= m; i++)
return 0;
}// int find(int x)
void calc(int now, long long mul, long long pls)
}void pushdown(int now)
int merge(int x, int y)
pushdown(x); pushdown(y);
if(kn[x].pow > kn[y].pow)
hp[x].rs = merge(hp[x].rs, y);
if(hp[hp[x].ls].dis < hp[hp[x].rs].dis)
hp[x].dis = hp[hp[x].rs].dis + 1;
return x;
}void dfs(int now, int fa)
while(hp[now].rt && kn[hp[now].rt].pow < ct[now].def)
if(ct[now].ai)
else
}void adde(int u, int v)
templatevoid rd(t & x)
} for( ; isdigit(ch); ch = getchar())
x *= fl;
}
JLOI2015 城池攻占 左偏樹
表示調這道題已經調到失智了。因為昨天剛寫完線段樹2,所以pushdown就寫得和線段樹2一模一樣,於是,成功的在pushdown的地方,各種錯 下面講做法 首先我們可以觀察到每個騎士都是獨立的,因此對於每個城池我們可以建乙個堆,堆中維護的是在這個城池的騎士。維護乙個小根堆,所以如果堆頂的騎士攻擊力不...
JLOI2015 城池攻占
霧.改變操作乘法是沒有負數的,那麼就不會改變大小關係,我們就可以dfs樹,然後用可合併堆進行操作。splay 啟發式合併也可以過 luogu 3261 bzoj 4003 include include include define int long long const int maxm 3100...
JLOI2015 城池攻占
點此看題 先把每個人放到對應的點上,可以用左偏樹,然後從下往上合併,每次就刪除當前節點會犧牲的人,然後維護乙個 加法 乘法 標記,時間複雜度o n log n o n log n o nlogn include include using namespace std define int long ...