分析:
聽說正解是fft+線段樹合併,然而我並不會...
我們來思考其他的方法。
我們要求的是連通塊第k大的和
對於某乙個連通塊,對答案的貢獻=val(rank.k)
我們不好直接算出每個連通塊的rank.k是多少
但我們可以列舉乙個limit for 1->w ,σ(val(rank.k)>=lim的連通塊的個數)就等於答案
為什麼呢,因為這樣乙個連通塊就被統計了val(rank.k)次。
剩下的進行樹形dp,設dp[i][j]為以i為根的子樹,選出j個權值》=limit的點的方案數。
那麼最後統計答案的時候便是σ(dp[i][j])(k<=j<=size(i))
複雜度n^3其實是不對的,但是卡一卡常數還是過得去的
**:
#include#include#include
#include
#include
#include
#include
#include
#include
#define rg register int
#define rep(i,a,b) for(rg i=a;i<=b;++i)
#define per(i,a,b) for(rg i=a;i>=b;--i)
#define ll long long
#define inf (1<<29)
#define maxn 2000
#define add(x,y) e[++cnt].v=y,e[cnt].next=head[x],head[x]=cnt
using
namespace
std;
intn,m,cnt,w;
intss[maxn],isn[maxn],head[maxn];
ll lim,ans;
ll val[maxn],dp[maxn][maxn],sz[maxn];
//dp[i][j] 在以i為根的子樹,選擇了j個權值大於等於lim的點的方案數
const ll mo=64123
;struct
ee[maxn
<<1
];inline
intread()
while(c>='
0'&&c<='9')
return x*f;
}inline
int mo(int x,int v)
void dfs(int u,int
fa) rep(i,m,sz[u]) ans=mo(ans,dp[u][i]);
}int
main()
cout
<
return0;
}
九省聯考 秘密襲擊
剛開始看起來像樹形dp,卻感覺無從下手 其實正解是fft 每個值的排名往上回溯時都會改變,後效性滿滿的。根本不是一次樹形dp能解決的。那麼,每個值對其他值的排名有什麼影響呢?我們發現只有比val i 大的值才會影響它的排名。不妨每次取乙個點出來,令值大於改點的值變為1,小於改點的值變為0,問題就轉化...
九省聯考 2018 秘密襲擊
題意 給定一顆含 n 個結點的樹,每個點有點權 d i 求所有聯通塊中第 k 大之和。1 leq n,m,k leq 1666,1 leq d i leq m 時間限制 5 秒。題解一道很有趣的題目。做法簡述 由於 dp 為卷積形式對其多項式求點值,並通過類似整體 dp 的方式維護變換,再通過拉格朗...
題解 九省聯考 2018 秘密襲擊 coat
可以將危險程度轉化為 列舉權值 t in 1,w 如果某個連通塊權值不小於 t 的節點個數不小於 k 個那麼造成 1 的貢獻。考慮 dp 令 f 表示以 u 為根子樹中包含 u 的連通塊,有 j 個權值不小於 i 的節點的方案數。轉移就是前兩維列舉,第三維做揹包。不妨令 f z sum limits...