[LOJ2537] PKUWC2018] 최소 최대

주제 링크

SIZE : https://loj.ac/problem/2537

루오 구 : https://www.luogu.org/problemnew/show/P5298

해결책

가끔 사기 죽은

긴 시간이 더 노크 코드는 실수 SB 많이하지


폭력 고려 \ (DP \)를 ,이 문제가 첫 번째 크기 관계 가중치를 사용하므로 별도의하자,하자 \ (F_ {X, 내가} \) 대표 \ (X \) 의 무게 점을 \ (ⅰ \) 확률.

물론 전송 :
[F_ {X, I} = F_ {LS, I} \ 좌측 (\ sum_ \ {. J의 = 1} ^ {. I- 1} p_x \ CDOT F_ {RS, J} + \ sum_ {J = I + 1} ^ {m} (1-p_x) \ cdot F_ {RS, J} \ 오른쪽) + F_ {RS, I} \ 좌측 (\ sum_ {J = 1} ^ {I-1} p_x \ cdot F_ {LS, J} + \
\ cdot F_ {LS는, J} \ 오른쪽) \] sum_ {J = I + 1} ^ {m} (1-p_x) 현재 열거 된 최대 값 또는 최소값으로부터 선택되는, 최적화 할 수 있고, 접두사 \ (O (N ^ -2) \) .

그리고 우리는이 일을, 각 세그먼트 트리 합병, 결합 된 처리 시간을 유지하고 접두사를 최적화하기 위해 나무 선 두께를 엽니 다.

시간 복잡도 \ (O (N- \ 기록 ^ N-2) \) , 공간 복잡도 \는 (O (N- \ N- 로그) \) .

암호

#include<bits/stdc++.h>
using namespace std;

void read(int &x) {
    x=0;int f=1;char ch=getchar();
    for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
    for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
}

void print(int x) {
    if(x<0) putchar('-'),x=-x;
    if(!x) return ;print(x/10),putchar(x%10+48);
}
void write(int x) {if(!x) putchar('0');else print(x);putchar('\n');}

#define lf double
#define ll long long 

#define pii pair<int,int >
#define vec vector<int >
#define mid ((l+r)>>1)

#define pb push_back
#define mp make_pair
#define fr first
#define sc second

#define FOR(i,l,r) for(int i=l,i##_r=r;i<=i##_r;i++) 

const int maxn = 4e5+10;
const int inf = 1e9;
const lf eps = 1e-8;
const int mod = 998244353;

int qpow(int a,int x) {
    int res=1;
    for(;x;x>>=1,a=1ll*a*a%mod) if(x&1) res=1ll*res*a%mod;
    return res;
}

int n,son[maxn][2],w[maxn],m,p,b[maxn];
int ls[maxn<<5],rs[maxn<<5],rt[maxn],s[maxn<<5],tag[maxn<<5],seg;

void push(int x,int c) {s[x]=1ll*s[x]*c%mod,tag[x]=1ll*tag[x]*c%mod;}

void pushdown(int x) {
    if(tag[x]!=1) push(ls[x],tag[x]),push(rs[x],tag[x]),tag[x]=1;
}

void insert(int &x,int l,int r,int c) {
    if(!x) x=++seg;s[x]=tag[x]=1;
    if(l==r) return ;
    if(c<=mid) insert(ls[x],l,mid,c);
    else insert(rs[x],mid+1,r,c);
}

int merge(int x,int y,int lsum=0,int rsum=0) {
    if(!x) return push(y,lsum),y;
    if(!y) return push(x,rsum),x;
    int t=++seg;tag[t]=1;pushdown(x),pushdown(y);
    int sl=s[ls[x]],sr=s[ls[y]];  // 注意这里递归的时候会被改掉,我就被坑了好久...
    ls[t]=merge(ls[x],ls[y],(lsum+1ll*(1-p+mod)*s[rs[x]]%mod)%mod,(rsum+1ll*(1-p+mod)*s[rs[y]]%mod)%mod);
    rs[t]=merge(rs[x],rs[y],(lsum+1ll*p*sl%mod)%mod,(rsum+1ll*p*sr%mod)%mod);
    s[t]=(s[ls[t]]+s[rs[t]])%mod;return t;
}

int solve(int x) {
    if(!son[x][0]) return insert(rt[x],1,m,lower_bound(b+1,b+m+1,w[x])-b),rt[x];
    int l=solve(son[x][0]);
    if(!son[x][1]) return l;
    int r=solve(son[x][1]);p=w[x];
    return merge(l,r);
}

int calc(int x,int l,int r) {
    if(!x) return 0;
    if(l==r) return 1ll*l*b[l]%mod*s[x]%mod*s[x]%mod;
    pushdown(x);
    return (calc(ls[x],l,mid)+calc(rs[x],mid+1,r))%mod;
}

int main() {
    read(n);int I=qpow(10000,mod-2),x;
    FOR(i,1,n) read(x),son[x][0]?son[x][1]=i:son[x][0]=i;
    FOR(i,1,n) read(x),son[i][0]?w[i]=1ll*x*I%mod:b[++m]=w[i]=x;
    sort(b+1,b+m+1);write(calc(solve(1),1,m));
    return 0;
}

추천

출처www.cnblogs.com/hbyer/p/10937986.html