掛了四分,掉了一名,不過這也說明我的實力就只有這點,根本不夠,果然以後還是直接【資料刪除】得了。
T1
其實就是個樹剖,每個點維護左右子樹的最大深度以及左右子樹內的最大答案,然後就…………沒了?
淦,也是實現問題,應該想到的。然後就是修改邊權是改成 \(w-a_p\),\(a_i\) 是記錄下來的 \(i\) 的父邊邊權。
真沒了
點選檢視程式碼
#include<bits/stdc++.h>
using namespace std;
#define ll int
#define ls now<<1
#define rs now<<1|1
const ll N=2*114514,M=1919810;
struct xx{
ll next,to;
}e[2*N];
ll head[2*N],cnt;
void add(ll x,ll y){
e[++cnt].next=head[x];
e[cnt].to=y;
head[x]=cnt;
}
ll n,m,fr[N];
ll in[N],out[N],t_cnt;
void dfs(ll u,ll fa){
in[u]=out[u]=++t_cnt;
for(int i=head[u];i;i=e[i].next){
ll v=e[i].to;
if(v==fa) continue;
dfs(v,u);
out[u]=++t_cnt;
}
}
struct tree{
ll res,tag;
ll mx,mn,lmx,rmx;
}t[4*N];
void modify(ll now,ll k){
t[now].mx+=k,t[now].mn+=k;
t[now].lmx-=k,t[now].rmx-=k;
t[now].tag+=k;
}
void pushup(ll now){
t[now].mx=max(t[ls].mx,t[rs].mx),t[now].mn=min(t[ls].mn,t[rs].mn);
t[now].lmx=max(max(t[ls].lmx,t[rs].lmx),t[ls].mx-2*t[rs].mn);
t[now].rmx=max(max(t[ls].rmx,t[rs].rmx),t[rs].mx-2*t[ls].mn);
t[now].res=max(t[ls].res,t[rs].res);
t[now].res=max(t[now].res,max(t[ls].mx+t[rs].rmx,t[rs].mx+t[ls].lmx));
}
void pushdown(ll now){
ll k=t[now].tag;
if(!k) return;
modify(ls,k),modify(rs,k);
t[now].tag=0;
}
void build(ll now,ll l,ll r){
if(l==r){
t[now].lmx=t[now].rmx=t[now].res=-1;
return;
}
ll mid=(l+r)>>1;
build(ls,l,mid);
build(rs,mid+1,r);
pushup(now);
}
void update(ll now,ll l,ll r,ll x,ll y,ll k){
if(l>=x&&r<=y){
modify(now,k);
return;
}
pushdown(now);
ll mid=(l+r)>>1;
if(x<=mid) update(ls,l,mid,x,y,k);
if(y>mid) update(rs,mid+1,r,x,y,k);
pushup(now);
}
ll p,w,a[N];
int main(){
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin>>n>>m;
for(int i=2;i<=n;++i){
cin>>fr[i];
add(i,fr[i]),add(fr[i],i);
}
build(1,1,n);
dfs(1,0);
for(int i=1;i<=m;++i){
cin>>p>>w;
update(1,1,t_cnt,in[p],out[p],w-a[p]);
a[p]=w;
cout<<t[1].res<<'\n';
}
return 0;
}/*5 4
1 1 2 2
4 8
4 3
2 2
5 7
擁有蒟蒻的力量,退役是必然的*/
T2
知道是個 dp,狀態設出來了,推不出來,太菜了
設 \(dp[u][i][j][k]\) 表示在 \(u\) 的子樹中選 \(u\) 並總共選了 \(i\) 個🐂,\(j\) 個🐏,\(k\) 個小C時的方案數。因為 \(A+B+C\le \frac{n}{2}\),所以對於 \(n\le 50\) 的資料直接 \(O(n(ABC)^2)\) 暴力 dp 就行了。
正解考慮樹形依賴揹包,透過我和想到的非常接近的 dp 可以做到 \(O(nABC)\),但是這樣只能算包含根結點的連通塊數,於是考慮套個點分治解決,複雜度 \(O(nABC\cdot\log n)\),點分治是我沒想到的/ng
需要注意的是,dp 陣列直接開 dp[201][201][201][201]
是要爆的,但是 \(A+B+C\le\frac{n}{2}\),所以可以考慮把後三維壓縮成一維,能存下。
不過為啥嚴隊程式碼是最裂解啊
點選檢視程式碼
#include<bits/stdc++.h>
using namespace std;
#define ll int
const ll N=205,M=55,mod=998244353;
ll cf[N][N];
struct xx{
ll next,to;
}e[2*N];
ll head[2*N],cnt;
void add(ll x,ll y){
e[++cnt].next=head[x];
e[cnt].to=y;
head[x]=cnt;
}
ll n,A,B,C,col[N],siz[N],ans;
ll dp[N][43999],vis[N],mx,rt,mxz; //米學長(霧
void findrt(ll u,ll fa){
siz[u]=1;
ll maxn=0;
for(int i=head[u];i;i=e[i].next){
ll v=e[i].to;
if(v==fa||vis[v]) continue;
findrt(v,u);
siz[u]+=siz[v];
maxn=max(maxn,siz[v]);
}
maxn=max(maxn,mxz-siz[u]);
if(mx>maxn) mx=maxn,rt=u;
}
ll dfn[N],t_cnt,c[N],sz[N];
void dfs(ll u,ll fa){
dfn[u]=++t_cnt;
c[t_cnt]=col[u];
sz[dfn[u]]=1;
for(int i=head[u];i;i=e[i].next){
ll v=e[i].to;
if(v==fa||vis[v]) continue;
dfs(v,u);
sz[dfn[u]]+=sz[dfn[v]];
}
}
ll &f(ll u,ll i,ll j,ll k){
return dp[u][i*(B+1)*(C+1)+j*(C+1)+k];
}
void solve(ll u){
memset(dp,0,sizeof(dp));
t_cnt=0,dfs(u,0);
f(1,0,0,0)=1;
for(int i=1;i<=t_cnt;++i)
for(int x=0;x<=A;++x)
for(int y=0;y<=B;++y)
for(int z=0;z<=C;++z){
ll val=f(i,x,y,z);
if(!val) continue;
if(c[i]==0&&x<A) (f(i+1,x+1,y,z)+=val)%=mod;
if(c[i]==1&&y<B) (f(i+1,x,y+1,z)+=val)%=mod;
if(c[i]==2&&z<C) (f(i+1,x,y,z+1)+=val)%=mod;
(f(i+sz[i],x,y,z)+=val)%=mod;
}
for(int x=0;x<=A;++x)
for(int y=0;y<=B;++y)
for(int z=0;z<=C;++z)
(ans+=f(t_cnt+1,x,y,z))%=mod;
--ans;
}
void calc(ll u){
vis[u]=1;
solve(u);
ll xxs=mxz;
for(int i=head[u];i;i=e[i].next){
ll v=e[i].to;
if(vis[v]) continue;
mxz=siz[u]>siz[v]?siz[v]:xxs-siz[u];
mx=1919810;
findrt(v,u),calc(rt);
}
}
int main(){
//freopen("b.in","r",stdin);
//freopen("b.out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin>>n>>A>>B>>C;
for(int i=1;i<=n;++i) cin>>col[i];
for(int i=1;i<n;++i){
ll a,b;
cin>>a>>b;
add(a,b),add(b,a);
}
mxz=n,mx=1919810;
findrt(1,0),calc(rt);
cout<<ans;
return 0;
}/*5 1 1 1
0 1 0 0 2
1 2
1 3
3 4
4 5
擁有蒟蒻的力量,退役是必然的*/
T3
xrq 場切,○| ̄|_ 不過講過我也做不來,賽時只有大眾分/ll