Luogu P5298 [PKUWC2018] Минимаксное

Jin хорошая тема ах, не пошел слитый сегмент дерева аспект , чтобы думать о ах

Во-первых, каждый из весов, вероятно, появится, так что мы первую строку последовательности и вероятность запроса

В это время, так как число диапазон становится \ ([. 1, м] \) (дискретное позже), мы можем установить на DP: \ (Р- {X, I} \) указывают узлы \ (Х \) из веса \ (я \) вероятность

Тогда точки передачи \ (х \) есть несколько обсуждение суб-узел, если не все, или только случайный перевод

Рассмотрю , если есть два, обозначаемый \ (ЖЕ \) и \ (гс \) , очевидно , мы можем перечислить уравнение переноса (В этой точке \ (я \) оставил свой сын, сын правой эмпатии):

\ [F_ {х,} = F_ {LC, я} \ раз (P_x \ Таймс \ sum_ {J = 1} ^ {я-1} F_ {гс, J} + (1-P_x) \ sum_ {J = + 1} ^ т F_ {гс, J}) \]

Мы обнаружили, что эта формула имеет некоторые характеристики: оно передается взять на себя некоторые префиксов и суффиксов, а с некоторыми, что если мы будем делать так, чтобы поддерживать обработку дерева линии

Так как каждый номер, а затем только в суб-дереве, другими словами, вероятность каждого числа в каждом узле приведет лишь к вкладу

Еще лучше, когда мы обнаружили целый ряд причин способствуют этому разделу, поскольку интервал умноженного диапазона номеров одинаковы, поэтому сделать отметку в то время, может пройти

В сочетании с деревом сегмента достигается общая сложность \ (О (п \ Log п ) \)

#include<cstdio>
#include<algorithm>
#define RI register int
#define CI const int&
using namespace std;
const int N=300005,mod=998244353;
struct edge
{
    int to,nxt;
}e[N]; int n,head[N],a[N],rst[N],cnt,num,x,rt[N],ans;
inline int sum(CI x,CI y)
{
    int t=x+y; return t>=mod?t-mod:t;
}
inline int sub(CI x,CI y)
{
    int t=x-y; return t<0?t+mod:t;
}
inline int quick_pow(int x,int p=mod-2,int mul=1)
{
    for (;p;p>>=1,x=1LL*x*x%mod) if (p&1) mul=1LL*mul*x%mod; return mul;
}
inline void addedge(CI x,CI y)
{
    e[++cnt]=(edge){y,head[x]}; head[x]=cnt;
}
class Segment_Tree
{
    private:
        struct segment
        {
            int ch[2],val,tag;
        }node[N*40]; int tot;
        #define lc(x) node[x].ch[0]
        #define rc(x) node[x].ch[1]
        #define V(x) node[x].val
        #define T(x) node[x].tag
        #define TN CI l=1,CI r=num
        inline void pushdown(CI now)
        {
            if (T(now)!=1) V(lc(now))=1LL*V(lc(now))*T(now)%mod,V(rc(now))=1LL*V(rc(now))*T(now)%mod,
            T(lc(now))=1LL*T(lc(now))*T(now)%mod,T(rc(now))=1LL*T(rc(now))*T(now)%mod,T(now)=1;
        }
    public:
        inline void insert(int& now,CI p,TN)
        {
            now=++tot; V(now)=T(now)=1; if (l==r) return; int mid=l+r>>1;
            if (p<=mid) insert(lc(now),p,l,mid); else insert(rc(now),p,mid+1,r);
        }
        inline int merge(CI x,CI y,CI p,CI lx=0,CI rx=0,CI ly=0,CI ry=0,TN)
        {
            if (!x&&!y) return 0; int now=++tot;
            if (!y) return pushdown(x),T(now)=sum(1LL*p*ly%mod,1LL*sub(1,p)*ry%mod),
            V(now)=1LL*V(x)*T(now)%mod,lc(now)=lc(x),rc(now)=rc(x),now;
            if (!x) return pushdown(y),T(now)=sum(1LL*p*lx%mod,1LL*sub(1,p)*rx%mod),
            V(now)=1LL*V(y)*T(now)%mod,lc(now)=lc(y),rc(now)=rc(y),now;
            int mid=l+r>>1; pushdown(x); pushdown(y); T(now)=1;
            lc(now)=merge(lc(x),lc(y),p,lx,sum(rx,V(rc(x))),ly,sum(ry,V(rc(y))),l,mid);
            rc(now)=merge(rc(x),rc(y),p,sum(lx,V(lc(x))),rx,sum(ly,V(lc(y))),ry,mid+1,r);
            return V(now)=sum(V(lc(now)),V(rc(now))),now;
        }
        inline int query(CI now,CI p,TN)
        {
            if (l==r) return V(now); pushdown(now); int mid=l+r>>1;
            if (p<=mid) return query(lc(now),p,l,mid); else return query(rc(now),p,mid+1,r);
        }
        #undef lc
        #undef rc
        #undef V
        #undef T
        #undef TN
}SEG;
#define to e[i].to
inline void DFS(CI now=1)
{
    if (!head[now]) return SEG.insert(rt[now],lower_bound(rst+1,rst+num+1,a[now])-rst);
    for (RI i=head[now];i;i=e[i].nxt) DFS(to),rt[now]=rt[now]?SEG.merge(rt[now],rt[to],a[now]):rt[to];
}
#undef to
int main()
{
    RI i; for (scanf("%d",&n),i=1;i<=n;++i) if (scanf("%d",&x),x) addedge(x,i);
    for (i=1;i<=n;++i) if (scanf("%d",&a[i]),head[i])
    a[i]=1LL*a[i]*quick_pow(10000)%mod; else rst[++num]=a[i];
    for (sort(rst+1,rst+num+1),DFS(),i=1;i<=num;++i)
    x=SEG.query(rt[1],i),ans=sum(ans,1LL*i*rst[i]%mod*x%mod*x%mod);
    return printf("%d",ans),0;
}

рекомендация

отwww.cnblogs.com/cjjsb/p/12078054.html