zoukankan      html  css  js  c++  java
  • [NOI2020]命运 题解

    考虑(dp.)

    (dp_{x,i})表示(x)子树内的所有边以及(x)(x)的父亲的边的状态(() 是否选取 ()) 都决定好了(,)目前还没有被解决的限制的最大深度(leq i)的方案数(.)

    不难发现转移时相当于每个儿子的(dp)数组对位相乘(,)最后要求一个当前(dp)数组的和加到全局上(.)

    可以用带(tag)的线段树合并维护(.)

    我的考场代码写的是启发式合并(.)

    启发式合并代码(:)

    #include <bits/stdc++.h>
    #define LL long long
    using namespace std;
    inline int read(){
    	static int x; static char c; x = 0,c = getchar();
    	while (!isdigit(c)) c = getchar();
    	while (isdigit(c)) x = x * 10 + c - '0',c = getchar();
    	return x;
    }
    const int N = 500050,P = 998244353;
    int To[N<<1],Ne[N<<1],He[N],_;
    inline void adde(int x,int y){
    	++_; To[_] = y,Ne[_] = He[x],He[x] = _;
    	++_; To[_] = x,Ne[_] = He[y],He[y] = _;
    }
    
    int n,m,fa[N],dpt[N],lim[N];
    inline void dfs(int x){
    	dpt[x] = dpt[fa[x]] + 1;
    	for (int y,p = He[x]; p ; p = Ne[p]) if ((y=To[p])^fa[x]) fa[y] = x,dfs(y);
    }
    
    
    const int V = N * 60;
    inline void upd(int &x,int y){ x = (x+y>=P)?(x+y-P):(x+y); }
    int lc[V],rc[V],val[V],mul[V],add[V],siz[V],cnto;
    int stk[V],top;
    inline int New(){
    	static int o; if (top) o = stk[top],--top; else o = ++cnto;
    	lc[o] = rc[o] = add[o] = siz[o] = val[o] = 0,mul[o] = 1;
    	return o;
    }
    inline void DD(int x){ stk[++top] = x; }
    inline void tmul(int o,int v){ if (o) mul[o] = (LL)mul[o] * v % P,add[o] = (LL)add[o] * v % P,val[o] = (LL)val[o] * v % P; }
    inline void tadd(int o,int v){ if (o) upd(add[o],v),upd(val[o],v); }
    inline void down(int o){
    	if (mul[o] ^ 1) tmul(lc[o],mul[o]),tmul(rc[o],mul[o]),mul[o] = 1;
    	if (add[o]) tadd(lc[o],add[o]),tadd(rc[o],add[o]),add[o] = 0;
    }
    inline void up(int o){ val[o] = val[rc[o] ? rc[o] : lc[o]],siz[o] = siz[lc[o]] + siz[rc[o]]; }
    int pp,vv;
    inline void Del(int &o,int l,int r){
    	if (!o || r < pp) return; if (l >= pp){ DD(o),o = 0; return; }
    	down(o); int mid = l+r>>1; Del(lc[o],l,mid); Del(rc[o],mid+1,r);
    	up(o); if (siz[o] == 0) DD(o),o = 0;
    }
    inline void Ins(int &o,int l,int r){
    	if (!o) o = New(); if (l == r){ siz[o] = 1,val[o] = vv; return; }
    	down(o); int mid = l+r>>1; if (pp <= mid) Ins(lc[o],l,mid); else Ins(rc[o],mid+1,r); up(o);
    }
    int ll,rr;
    inline void Mul(int o,int l,int r){
    	if (!o) return; if (ll <= l && rr >= r){ tmul(o,vv); return; }
    	down(o); int mid = l+r>>1; if (ll <= mid) Mul(lc[o],l,mid); if (rr > mid) Mul(rc[o],mid+1,r); up(o);
    }
    inline void Add(int o,int l,int r){
    	if (!o) return; if (ll <= l && rr >= r){ tadd(o,vv); return; }
    	down(o); int mid = l+r>>1; if (ll <= mid) Add(lc[o],l,mid); if (rr > mid) Add(rc[o],mid+1,r); up(o);
    }
    
    inline bool Is(int o,int l,int r){
    	if (!o) return 0; if (l == r) return 1;
    	down(o); int mid = l+r>>1; if (pp <= mid) return Is(lc[o],l,mid); return Is(rc[o],mid+1,r);
    }
    int qans,qi;
    inline void Query(int o,int l,int r){
    	if (!o || qi >= r || l >= pp) return; if (r < pp){ qi = r,qans = val[o]; return; }
    	down(o); int mid = l+r>>1; Query(rc[o],mid+1,r); Query(lc[o],l,mid);
    }
    inline void radd(int rt,int l,int r,int v){ ll = l,rr = r,vv = v,Add(rt,0,n); }
    inline void rmul(int rt,int l,int r,int v){ ll = l,rr = r,vv = v,Mul(rt,0,n); }
    inline void rins(int &rt,int p,int v){ pp = p,vv = v,Ins(rt,0,n); }
    inline void rdel(int &rt,int p){ pp = p,Del(rt,0,n); }
    inline bool ris(int rt,int p){ pp = p; return Is(rt,0,n); } 
    
    int ti[N],tv[N],cntt;
    inline void Dfs(int o,int l,int r){
    	if (!o) return; if (l == r){ ++cntt; ti[cntt] = l,tv[cntt] = val[o]; DD(o); return; }
    	down(o); int mid = l+r>>1; Dfs(lc[o],l,mid); Dfs(rc[o],mid+1,r); DD(o);
    }
    
    int ans;
    inline void Ask(int o,int l,int r){
    	if (!o) return; if (l == r){ ans = val[o]; return; }
    	down(o); int mid = l+r>>1; if (lc[o]) Ask(lc[o],l,mid); else Ask(rc[o],mid+1,r);
    }
    
    inline void Dfs2(int o,int l,int r){
    	if (!o) return; if (l == r){ ++cntt; ti[cntt] = l,tv[cntt] = val[o]; return; }
    	down(o); int mid = l+r>>1; Dfs2(lc[o],l,mid); Dfs2(rc[o],mid+1,r); 
    }
    
    inline int Merge(int rt1,int rt2){
    	if (siz[rt1] < siz[rt2]) swap(rt1,rt2);
    	cntt = 0,Dfs(rt2,0,n);
    	ti[++cntt] = n+1;
    	for (int i = cntt-1; i >= 1; --i){
    		if (!ris(rt1,ti[i])){
    			pp = ti[i],qi = -1,Query(rt1,0,n);
    			rins(rt1,ti[i],qans);
    		}
    		rmul(rt1,ti[i],ti[i+1]-1,tv[i]);
    	}
    	return rt1;
    }
    
    int T[N];
    inline void dp(int x){
    	if (lim[x]) rins(T[x],0,0); rins(T[x],lim[x],1);
    	for (int y,p = He[x]; p ; p = Ne[p]) if ((y=To[p])^fa[x]) dp(y),T[x] = Merge(T[x],T[y]);
    	if (x == 1){ Ask(T[1],0,n); return; }
    	radd(T[x],0,n,val[T[x]]);
    	rdel(T[x],dpt[fa[x]]);
    	//cerr << "print " << x <<'
    ',Print(T[x]);
    }
    
    int main(){
    //	freopen("destiny.in","r",stdin);
    //	freopen("destiny.out","w",stdout);
    	int i,x,y;
    	n = read();
    	for (i = 1; i < n; ++i) x = read(),y = read(),adde(x,y);
    	dfs(1);
    	for (i = 1; i <= n; ++i) lim[i] = 0;
    	m = read();
    	while (m--) x = read(),y = read(),lim[y] = max(lim[y],dpt[x]);
    	dp(1);
    	cout << ans << '
    ';
    }
    
  • 相关阅读:
    How to Create a site at the specified URL and new database (CommandLine Operation)
    Using Wppackager to Package and Deploy Web Parts for Microsoft SharePoint Products and Technologies
    SQL Server Monitor v0.5 [Free tool]
    How to build Web Part
    Deploy web part in a virtual server by developing a Web Part Package file(.cab)
    How to recreate "sites" link if you delete it accidentally
    SharePoint Portal Server管理匿名访问设置
    Monitor sql connection from .Net SqlClient Data Provider
    Brief installation instruction of Sharepoint Portal Server
    How to Use SharePoint Alternate URL Access
  • 原文地址:https://www.cnblogs.com/s-r-f/p/13581278.html
Copyright © 2011-2022 走看看