題面戳我!
我們發現「所有數加起來等於線索上的權值」這個東西可以用流量平衡來解決,所以可以跑上下界費用流。
建圖就是,把上下線索放左邊,左右線索放右邊,源點向所有上下線索連乙個上下界均為對應權值的邊,同理左右線索向匯點連乙個上下界均為對應權值的邊;對於空格就是把左邊的乙個節點和右邊的乙個節點連起來,上下界均為這個空格的初始權值。
然後考慮調整,以上建的每條邊都可以調整流量(正向表示權值加,反向表示權值減),注意反向要限制流量為對應初始權值減 \(1\),這樣來保證最終都是正整數。如果代價為 \(-1\),可以直接不建調整的邊。
#include #include #include #include #include #include #include using namespace std;
#define rep(i, s, t) for(int i = (s), mi = (t); i <= mi; i++)
#define dwn(i, s, t) for(int i = (s), mi = (t); i >= mi; i--)
int read()
while(isdigit(c))
return x * f;
}#define maxn 1810
#define maxm 14420
#define ll long long
#define oo 2147483647
#define ool (1ll << 60)
struct edge
edge(int _1, int _2, int _3, int _4): from(_1), to(_2), flow(_3), cost(_4) {}
};struct zkw
void setn(int _)
void addedge(int a, int b, int c, int d)
int nxt(int x)
bool bfs()
}} if(d[s] == ool) return 0;
cost = d[s];
return 1; }
int dfs(int u, int a)
} return flow; }
int maxflow(int _s, int _t) while(f);
return flow;
}} sol;
#define maxr 35
struct grid gs[maxr][maxr];
int cntp, ind[maxn];
struct point
int p()
} ud[maxr][maxr], lr[maxr][maxr], s, t, ss, tt;
int main()
rep(i, 1, n) rep(j, 1, m)
sol.init();
rep(i, 1, n) rep(j, 1, m)
} if(gs[i][j].tp == 2 || gs[i][j].tp == 3)
} if(gs[i][j].tp == 4)
} }sol.addedge(t.p(), s.p(), oo, 0);
int sum = 0;
rep(i, 1, cntp)
sol.setn(cntp);
int flow = sol.maxflow(ss.p(), tt.p());
if(flow < sum) return puts("-1"), 0;
printf("%lld\n", sol.ans);
fclose(stdin);
fclose(stdout);
return 0;
}
我們將線索看成點,空格就是連線恰好兩個點的無向邊。把這個圖建出來,隨便選一棵生成樹,非樹邊就隨機一下權值,樹邊權值就可以確定了(可通過非樹邊的權值和點權從深往淺遞推)。
#include #include #include #include #include #include #include using namespace std;
#define rep(i, s, t) for(int i = (s), mi = (t); i <= mi; i++)
#define dwn(i, s, t) for(int i = (s), mi = (t); i >= mi; i--)
#define ll long long
ll read()
while(isdigit(c))
return x * f;
}#define maxr 210
#define maxn 80010
#define maxm 160010
ll get_rand()
int r, c;
struct grid gs[maxr][maxr];
int cntp, eid[maxr][maxr];
ll val[maxn];
struct point
int p()
} ud[maxr][maxr], lr[maxr][maxr];
int m, m, head[maxn], nxt[maxm], to[maxm], id[maxm];
void addedge(int a, int b, int i)
short vis[maxn], ok;
ll ans[maxn];
void dfs(int u, int fa)
else if(!vis[to[e]])
} if(!fa && val[u]) ok = 0;
vis[u] = 1;
return ;
}map has;
void work()
cntp = m = m = 0; memset(head, 0, sizeof(head));
rep(i, 1, r) rep(j, 1, c) if(gs[i][j].tp == 4)
memset(vis, 0, sizeof(vis)); ok = 1;
rep(i, 1, cntp) if(!vis[i])
has.clear();
rep(i, 1, m)
rep(i, 1, r)
return ;
}int main()
這個每條資訊的候選數都是一段連續的區間最多去掉乙個數字【需要分情況討論,當 \(len \le 2\)(\(len\) 表示線索限制的區間長度)時候選數字是單點】。於是我們可以用乙個掃瞄線從上往下掃瞄這個網格,遇到乙個縱向的線索的開頭就加入資料結構,結尾就從資料結構刪除,然後對於乙個橫向的線索相當於區間查詢資訊。我們開乙個線段樹套線段樹,外層位置內層值域,維護左右端點的總和(如果候選數字是貼著 \(k\) 的區間就存左端點,是貼著 \(1\) 的區間就存右斷電)、刪除的單點,以及如果候選數字是單點就維護一下這個單點資訊。
具體實現我也不會,就是不知道如何求出刪掉哪個值,感覺這種分類討論題非常噁心
位元組跳動冬令營2018
給定一棵有根樹,邊有邊權,兩個人輪流操作,每次可以把一條邊的權值減少一,權值變為 0 表示把子樹砍掉,問先手第一輪操作哪些邊使得自己必勝。n 1 06 n leq 10 6 n 10 6之前的部落格,發現這道題本質上是圖的刪邊遊戲。把環縮掉,就變成了樹上刪邊遊戲了。結論是 葉子的 sg 為 0,非葉...
道路重建 2018山東冬令營
時間限制 1 sec 記憶體限制 128 mb 提交 67 解決 24 提交 狀態 討論版 小l的家鄉最近遭遇了一場洪水,城市變得面目全非,道路也都被沖毀了。生活還要繼續,於是市 決定重建城市中的道路。在洪水到來前,城市中共有n個區域和m條連線這些區域的雙向道路,道路連通了所有的區域,為了方便人們的...
2015 2 1冬令營日誌
今天的任務 1.寫一篇部落格。2.寫乙個週報。3.聽張老師的講座,感覺還是獲益匪淺。他說我們學校的軟體工程專業現況是有實力與清華北大媲美的,這讓我感到十分榮幸,雖然沒有親自去過清華北大,但這兩所學校的名氣確實是如雷貫耳的,瞬間覺得我還是走上了乙個高富帥的專業。但是,以後的事情還是需要我繼續努力堅持才...