在平面上有n條平行於y軸的線段,每條線段都有乙個權值,每次可以找出的y軸上投影互不重疊的若干線段,求m次後,找出的線段最大權值和為多少。(每條線段只能貢獻一次)
對於30%的資料,n<=100;m<=2;1<=y1考慮費用流,找m次可以當做總流量為m,然後首先的暴力方法是對於每條線段,與它互不重疊的線段連邊,這樣邊數是o(n
2)
o(n^2)
o(n2
)的,並不能過.
然後這裡好像算是乙個常見技巧:對數軸建邊,注意到由於是在y軸投影上互不重疊,所以x座標是沒有用的.所有的座標只有o
(5000
)o(5000)
o(5000
)級別,所以我們建出(i,i+1,inf,0)這種邊,形成縱座標軸,然後把原來的線段,流量為1,費用是權值,直接建在軸上,跑最大費用最大流.
考慮這樣的正確性,一條線段被選了以後,一條和它不相交的線段不會多增加流量,而一條和它相交的邊則會增加流量.所以正確.
#include
using
namespace std;
#define int long long
const
int maxn=
2e4+5;
const
int inf=
0x3f3f3f3f3f3f3f3fll
;inline
intread()
while
(isdigit
(c)&&
(c!=
eof)
)return t*f;
}int n,m,s;
struct edgee[maxn<<2]
;int h[maxn]
,cnt=1;
inline
void
add(
int a,
int b,
int c,
int d)
int cost,dis[maxn]
,vis[maxn]
,ht[maxn]
,t;bool
bfs()}
}}return dis[t]
!=st;
}int
dfs(
int u,
int rest)
vis[u]=1
;int tot=0;
for(
int&i=ht[u]
;i;i=e[i]
.p)}
return tot;
}void
dinic()
}}signed
main()
//printf("%d\n",s);
for(
int i=
1;i<
5e3+
5;i++
)//printf("%d\n",s);
dinic()
;printf
("%lld\n"
,cost)
;return0;
}
一道互動練習題
的做法 考慮逐位確定 對於每個位置,往後列舉有沒有位置可以使得正確位置更多,如果有,那麼有兩種情況,1是這個位置被放到了正確的位置,2是這個位置本來應該放的數被放來了 這裡的重點是我們需要區分1和2 具體的做法是記下讓這個位置答案正確位置數變大的2個位置,將其和i一起移位 這裡是手繪示意圖.即把p1...
一道fft練習題
考場上想到的o n 2 o n 2 o n2 暴力 記f i j f i j f i j 表示前i個位置,長度為j的連擊出現的期望次數 記g i j g i j g i j 表示第到i個位置為止,目前連擊次數為j的概率 轉移時有一些細節 include using namespace std con...
一道sam練習題
考慮答案實際上是每個子串的出現次數的平方和.這個可以通過手玩樣例驗證.考慮廣義sam 先將所有字串建成trie,然後再在trie上bfs,建出sam.考慮fail樹 每次插入乙個新節點,會改變從這個節點開始到根的路徑上的每個節點的right集合大小.所以考慮樹剖維護這種操作,然後每乙個單詞的答案就是...