JLOI2015 城池攻占

2022-02-02 16:56:40 字數 1106 閱讀 2668

原題位址

首先發現乘的時候 係數不會為負,所以能得到乙個關鍵條件:變化後的戰鬥力隨變化前的戰鬥力大小單調

所以我們考慮倍增

設hp[x][i]是從x開始一路攻克\(2^i\)個城池所需要最小的初始生命值

設trans[x][i][0/1]是攻克了\(2^i\)個城池後攻擊力的變化量,0表示乘,1表示加,先乘後加

注意乘的係數初始化成1

然後就可以倍增了

然而空間大小惡意卡倍增

但是我們這個倍增可以換成三進製的

就是把定義裡的\(2^i\)都換成\(3^i\)

於是\(log_3300000=10\),空間就變成了原來的一半

需要注意的一點是,最後在跳倍增的時候,同乙個長度可以跳兩次(因為是三進製嘛),迴圈的時候稍微注意一下

#include#define pa pair#define clr(a,x) memset(a,x,sizeof(a))

#define mp make_pair

using namespace std;

typedef long long ll;

const int maxn=3e5+5;

inline char gc()

inline ll rd()

while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+c-'0',c=gc();

return neg?(~x+1):x;

}int n,m,fa[maxn][11];

ll hp[maxn][11],trans[maxn][11][2];

int ans1[maxn],ans2[maxn];

int pw3[11];

int main()

}for(i=1;i<=m;i++)

}if(x!=-1) ans1[x]++;

ans2[i]=n;

}for(i=1;i<=n;i++)

printf("%d\n",ans1[i]);

for(i=1;i<=m;i++)

printf("%d\n",ans2[i]);

return 0;

}

幸甚至哉,歌以詠志。

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 ...

JLOI2015 城池攻占

左偏樹的題。把每個節點上有的騎士按照攻擊力的大小建乙個小根堆。dfs的時候把兒子們的都合併過來,看看update完了的值是否小於防禦值。小於的話就pop,然後ans x 記得開long long include include include using namespace std define i...