八 九省聯考2018

2022-03-25 18:28:01 字數 3302 閱讀 2538

luogu

lojbzoj

為了方便我們把整個過程倒過來,保證最後一步行動的人是先手(菲菲)。

不難發現任意時刻都存在乙個右上-左下的輪廓線。

這個輪廓線從\((0,m)\rightarrow(n,0)\),共有\(n+m\)條邊,我們用\(0\)表示向左,\(1\)表示向下,那麼一條輪廓線就可以按順序被壓縮成乙個\(n+m\)位的二進位制數。

然後我們用\(0,1\)分別表示先手後手,設\(f_\)表示輪廓線狀態為\(i\),下乙個操作的人是\(j\)時\(!j\)的最高得分。

轉移就找到輪廓線中所有「下-右」型的可以放棋子的角落,然後列舉放哪個即可。

#include#includeint a[2][12][12],f[1<<20][2];

int read()

void max(int&a,int b)

int main()

,n],f_j\leftarrow f_j+size_-1\)。

線段樹維護\(f\)即可。

維護每個數值最右邊的未被選取的位置可以先讓每個位置連到數值相等的最右邊的位置,再從這個點連到最右邊的未被選取的位置即可。

#include#include#includeconst int n=500007;

int n,a[n],next[n],fa[n],size[n],ans[n],t[n*4],tag[n*4];double k;

int read()

#define ls p<<1

#define rs p<<1|1

#define mid ((l+r)/2)

void pushup(int p)

void modify(int p,int v)

void pushdown(int p)

void build(int p,int l,int r)

void update(int p,int l,int r,int l,int r,int x)

int find(int p,int l,int r,int x)

\)表示考慮到\(u\)點時有多少個連通塊中\(r\)的排名為\(i\)。

初始狀態為\(f_=1\)。

對於點\(u\),如果\(u\)比\(r\)危險,那麼\(f_=f_\),否則\(f_=f_\)。

做完\(u\)的子樹之後再\(f_\leftarrow f_+f_\)。

那麼這種情況下對答案的貢獻為\(f_d_r\)。

這個做法的時間複雜度為\(o(n^2k)\)

(正解做法是線段樹合併維護點值+lagrange插值)

#include#include#includeusing u32=unsigned int;

const int n=2007;const u32 p=64123;

int n,k,d[n];u32 f[n][n];std::vectore[n];

int read()

void inc(u32&a,u32 b)

u32 mul(u32 a,u32 b)

int cal(int u)

void dfs(int u,int fa,int root)

int dfs(int u,int k)

return 0;

}void solve()

if(j<=s[i]) up[i]=std::min(up[i],i-mx);}}

for(int i=1;i<=n;++i) printf("%d ",id[i]);puts("");

for(int i=1;i<=n;++i) printf("%d ",up[i]);puts("");

}int main()

luogu

lojbzoj

不難發現題目就是要我們找\(k+1\)條點不相交的樹上路徑,使得它們的長度和最大。

乙個很簡單的貪心做法是每次選擇當前的直徑,並把直徑上的邊權取反。

但是這個做法拓展性不強,考慮dp。

設\(f_\)表示在\(u\)的子樹中選\(i\)條鏈,\(u\)的度數為\(0/1/2\)時的答案。

轉移分為兩種,討論\((u,v)\)這條邊選還是不選即可,時間複雜度為\(o(n^2)\)。

設\(g_=\max\|k\in[0,2]\}\),打表發現\(g_\)關於\(i\)是乙個凸函式。

然後凸優化即可。

#include#include#include#include#includeusing i64=long long;

using pi=std::pair;

const int n=300007;

int n,k,cost;std::vectore[n];

struct nodef[n][3],g[n],t[3];

node operator+(node a,node b);}

int operator<(node a,node b)

int read()

void dfs(int u,int fa)

,f[u][1]=,f[u][2]=g[u]=;

for(auto[v,w]:e[u])

),f[u][2]=std::max(f[u][2],node);

}for(int i=0;i<3;++i) g[u]=std::max(g[u],f[u][i]);

}int main()

;struct nodet[n*20];

data operator+(data a,data b);}

int read()

#define mid ((l+r)/2)

void insert(int&p,int l,int r,int x)

; if(l^r) x<=mid? insert(t[p].ls,l,mid,x):insert(t[p].rs,mid+1,r,x);

}int merge(int u,int v)

data query(int p,int l,int r,int l,int r)

; if(l<=l&&r<=r) return t[p].x;

return query(t[p].ls,l,mid,l,r)+query(t[p].rs,mid+1,r,l,r);

}int queryl(int p,int l,int r,int x)

int queryr(int p,int l,int r,int x)

#undef mid

void extend(int c)

void build()

void solve()

int main()

九省聯考 2018

發現狀態數很少,直接搜即可。不難發現這個偏序關係形成了一棵樹。本來以為直接貪心即可,即把 a 排序,然後 dfs bfs 一遍直接安排權值,類似於這樣 void dfs1 int u void dfs2 int u 不出我所料,這份簡單的 沒有過,被這組資料叉掉了 2 2.0 1 1 1 2發現這樣...

九省聯考2018遊記

day0 上午到學校,去tututu寢室,入坑荒野求生,真tm好玩 雖然只打了一把 下午坐高鐵去sh,發現sh非正式選手只有hez的。day1 開局看t1,沒意識到狀態數是個組合數,於是寫了個程式算狀態數,還寫掛了 include int n 10,m 10,f 15 15 i,j,k int ma...

八省聯考2018 劈配

題目這題目,乍一眼看上去像乙個dp,因為這個資料範圍一般都是dp,但是考慮到轉移有後效性,所以顯然是做不了dp的。考試的時候像著怎麼設狀態沒有後效性,失敗了,就只打了乙個70分的暴力,還掛了20分。這題其實是個 網路流 匹配 真心看不出,然後我寫部落格的時候旁邊yl神犇看見了,嘲諷了我一波,我是真的...