私密:平衡序列(官方题解_原创版权)
线段树+差分 其实就是线段树
用一颗线段树维护以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);
}