私密:平衡序列(官方题解_原创版权)

线段树+差分 其实就是线段树

用一颗线段树维护以i为根的子树获得的所有乘积,求出子树的最大dfn,然后乘法差分。

复杂度近似\(O(n\space log\space n)\)

STD用了两个线段树,需要特判,常数da。

#include<bits/stdc++.h>
#define ll long long
#define db ll
#define il inline
#define f(i,a,b) for(ll i=a;i<=b;i++)
ll n,m,ci,lc,rc,k;
db a[100005];
il ll read(){scanf("%lld",&ci);return ci;}
const ll maxn=1e5+10,P=1e9+7;
using namespace std;
struct node{ll L,R,tag=1,w=1;} tree[500005];
ll iv[maxn];
il void chen(ll &x,ll y){
    x=(x*y)%P;
}
inline ll build(ll l,ll r,ll p){
    ll mid=(l+r)/2;
    tree[p].L=l,tree[p].R=r;
//	if(p==54273) cout<<tree[p].L<<" "<<tree[p].R<<endl;
    if(l==r) return (tree[p].w=1);
    tree[p].w=(build(l,mid,p*2)+build(mid+1,r,p*2+1))%P;
    // cout<<(build(l,mid,p*2)+build(mid+1,r,p*2+1))%P<<endl;
//    if(p==54273) cout<<tree[p].w<<endl;
    return tree[p].w;
}
inline void give(ll p){
    chen(tree[p*2].tag,tree[p].tag);chen(tree[p*2+1].tag,tree[p].tag);
    chen(tree[p*2].w,tree[p].tag);chen(tree[p*2+1].w,tree[p].tag);
    tree[p].tag=1;
}
inline void add(ll p,ll l,ll r,ll k){
    if(l>tree[p].R||r<tree[p].L) return;
    if(tree[p].L>=l&&tree[p].R<=r) {chen(tree[p].w,k);chen(tree[p].tag,k);return;}
    if(tree[p].tag) give(p);
    add(p*2,l,r,k);add(p*2+1,l,r,k);
    tree[p].w=(tree[p*2].w+tree[p*2+1].w)%P;
}
inline db ask(ll p,ll l,ll r){
    if(l>tree[p].R||r<tree[p].L) return 0;
    if(tree[p].L>=l&&tree[p].R<=r){
//    	cout<<p<<endl; 
		return tree[p].w;
	}
    if(tree[p].tag) give(p);
    return (ask(p*2,l,r)+ask(p*2+1,l,r))%P;
}
ll fa[maxn],dfn[maxn],siz[maxn],fir[maxn],cnt,t;
struct edge{ll to,nex;}e[maxn<<1];
il void eadd(ll x,ll y){e[++cnt].to=y;e[cnt].nex=fir[x];fir[x]=cnt;}
il void dfs(ll x,ll f){
    siz[x]=1,dfn[x]=++t;
    // cout<<x<<endl;
    for(ll i=fir[x];i;i=e[i].nex){
        ll v=e[i].to;
        if(v==f) continue;
        dfs(v,x);
        siz[x]+=siz[v];
    }
}
int main(){
    // freopen("a6.in","r",stdin);
    // freopen("a10.in","r",stdin);
    // freopen("a10.out","w",stdout);
    iv[1]=1;
    f(i,2,maxn-10){iv[i]=(P-P/i)*(iv[P%i])%P;}
    // f(i,2,maxn) cout<<iv[i-1]<<" ";
    // f(i,1,maxn) cout<<iv[i]<<" ";
    n=read(),m=read();
    f(i,2,n){ll u=read();eadd(u,i);eadd(i,u);}
    dfs(1,0);
    build(1,n,1);
//    cout<<tree[1].w<<endl;
//    return 0;
    f(i,1,m){
        ll l=read(),r=read();
        ll op=read(),k=(tree[1].w)%(maxn-10)+1;
        if(op==2) k=iv[k];
       // cout<<k<<endl;
        add(1,l,r,k);
    }
    f(i,1,n) a[i]=ask(1,i,i);
    build(1,n,1);
    f(i,1,n) add(1,dfn[i],dfn[i]+siz[i]-1,a[i]);
    printf("%lld",tree[1].w);
}
posted @ 2021-10-29 13:56  yf1987  阅读(27)  评论(0编辑  收藏  举报