日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

P6773-[NOI2020]命运【线段树合并,树形dp】

發布時間:2023/12/3 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 P6773-[NOI2020]命运【线段树合并,树形dp】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

正題

題目鏈接:https://www.luogu.com.cn/problem/P6773


題目大意

nnn個點的一棵樹,邊權可以是000111mmm個條件(x,y)(x,y)(x,y)表示要求x,yx,yx,y之間要有邊權值為111(保證xxxyyy的祖先),求方案數。


解題思路

考慮容斥,首先我們把沒有用的條件去掉(就是被其他條件包含的),如果有kkk條路徑上沒有111那么容斥系數為∣?1∣k|-1|^k?1k

fi,jf_{i,j}fi,j?表示點iii的子樹中,要再往上到深度為jjj的節點都不能是111時的答案,那么有轉移方程fx,min{j,k}=fx,j?fy,kf_{x,min\{j,k\}}=f_{x,j}*f_{y,k}fx,min{j,k}?=fx,j??fy,k?
這是一個min?maxmin-maxmin?max卷積的形式,用線段樹合并維護即可。

時間復雜度O(nlog?n)O(n\log n)O(nlogn)


codecodecode

#include<cstdio> #include<cstring> #include<algorithm> #define ll long long using namespace std; const ll N=5e5+10,XJQ=998244353; struct node{ll to,next; }a[N*2]; ll n,m,tot,ls[N],dep[N],rt[N],up[N]; struct Seq_Tree{ll cnt,w[N<<6],ls[N<<6],rs[N<<6],lazy[N<<6];void Downdata(ll x){if(lazy[x]==1)return;w[ls[x]]=w[ls[x]]*lazy[x]%XJQ;w[rs[x]]=w[rs[x]]*lazy[x]%XJQ;lazy[ls[x]]=lazy[ls[x]]*lazy[x]%XJQ;lazy[rs[x]]=lazy[rs[x]]*lazy[x]%XJQ;lazy[x]=1;return;}void Insert(ll &x,ll L,ll R,ll pos,ll val){if(!x)x=++cnt,lazy[x]=1;if(L==R){w[x]+=val;return;}ll mid=(L+R)>>1;Downdata(x);if(pos<=mid)Insert(ls[x],L,mid,pos,val);else Insert(rs[x],mid+1,R,pos,val);w[x]=(w[ls[x]]+w[rs[x]])%XJQ;return;}void Change(ll &x,ll L,ll R,ll l,ll r){if(!x)x=++cnt,lazy[x]=1;if(L==l&&R==r){lazy[x]=lazy[x]*2%XJQ;w[x]=w[x]*2%XJQ;return;}ll mid=(L+R)>>1;Downdata(x);if(r<=mid)Change(ls[x],L,mid,l,r);else if(l>mid)Change(rs[x],mid+1,R,l,r);else Change(ls[x],L,mid,l,mid),Change(rs[x],mid+1,R,mid+1,r);w[x]=(w[ls[x]]+w[rs[x]])%XJQ;return;}ll Merge(ll x,ll y,ll l,ll r,ll w1,ll w2){if(!x||!y){w[x]=w[x]*w2%XJQ;lazy[x]=lazy[x]*w2%XJQ;w[y]=w[y]*w1%XJQ;lazy[y]=lazy[y]*w1%XJQ;return x+y;}if(l==r){w[x]=(w[x]*w[y]+w[x]*w2+w[y]*w1)%XJQ;return x;}ll mid=(l+r)>>1;Downdata(x);Downdata(y);ls[x]=Merge(ls[x],ls[y],l,mid,(w1+w[rs[x]])%XJQ,(w2+w[rs[y]])%XJQ);rs[x]=Merge(rs[x],rs[y],mid+1,r,w1,w2);w[x]=(w[ls[x]]+w[rs[x]])%XJQ;return x; } }T; void addl(ll x,ll y){a[++tot].to=y;a[tot].next=ls[x];ls[x]=tot;return; } void dfs(ll x,ll fa){dep[x]=dep[fa]+1;for(ll i=ls[x];i;i=a[i].next){ll y=a[i].to;if(y==fa)continue;dfs(y,x);}return; } void solve(ll x,ll fa){if(up[x])T.Insert(rt[x],1,n,up[x],XJQ-1);T.Insert(rt[x],1,n,n,1);for(ll i=ls[x];i;i=a[i].next){ll y=a[i].to;if(y==fa)continue;solve(y,x);T.Change(rt[y],1,n,dep[y],n);rt[x]=T.Merge(rt[x],rt[y],1,n,0,0);} // printf("%d\n",T.w[rt[x]]);return; } int main() {scanf("%lld",&n);for(ll i=1;i<n;i++){ll x,y;scanf("%lld%lld",&x,&y);addl(x,y);addl(y,x);}dfs(1,0);scanf("%lld",&m);while(m--){ll x,y;scanf("%lld%lld",&x,&y);up[y]=max(up[y],dep[x]);}solve(1,0);printf("%lld",T.w[rt[1]]);return 0; }

總結

以上是生活随笔為你收集整理的P6773-[NOI2020]命运【线段树合并,树形dp】的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。