3 条题解
-
112322132131231 (褚战) LV 10 @ 2023-07-12 17:37:57
#include<bits/stdc++.h> using std::list; typedef long long ll; const int N=100011; int n,a[N];list<int>vec[N],e[N]; int RT[N]; struct node{ ll v,pd,d,pdxd;// Σ1,Σdep[pre],Σdep[i],Σdep[pre]×dep[i] node operator+(const node&t){return node{v+t.v,pd+t.pd,d+t.d,pdxd+t.pdxd};} node operator-(const node&t){return node{v-t.v,pd-t.pd,d-t.d,pdxd-t.pdxd};} }; struct prt{ int sz,ls[N*20],rs[N*20]; node s[N*20]; void build(int&x,int l,int r){ s[x=++sz]=node{0,0,0,0}; if(l==r)return; int m=l+r>>1; build(ls[x],l,m);build(rs[x],m+1,r); } void ins(int&x,int pre,int p,int l,int r,node v){ s[x=++sz]=s[pre]+v; if(l==r)return; ls[x]=ls[pre],rs[x]=rs[pre]; int m=l+r>>1; if(p<=m)ins(ls[x],ls[pre],p,l,m,v); else ins(rs[x],rs[pre],p,m+1,r,v); } node ask(int x,int y,int R,int l,int r){ if(r<=R)return s[y]-s[x]; int m=l+r>>1; node ans=ask(ls[x],ls[y],R,l,m); return R>m?ans+ask(rs[x],rs[y],R,m+1,r):ans; } }T; int L[N],R[N],dfn,st[20][N*2]; int f[N],d[N],pre[N],b[N];ll sum[N][2]; void dfs(int x){ st[0][L[x]=++dfn]=x; pre[x]=b[a[x]],b[a[x]]=x; T.ins(RT[x],RT[f[x]],pre[x],0,n,node{ 1,d[pre[x]],d[x],1ll*d[pre[x]]*d[x] }); sum[x][0]=d[x]-d[pre[x]]+sum[f[x]][0]; sum[x][1]=1ll*(d[x]-d[pre[x]])*d[x]+sum[f[x]][1]; for(int to:e[x])d[to]=d[x]+1,dfs(to),st[0][++dfn]=x; R[x]=dfn; b[a[x]]=pre[x]; } int gmd(int x,int y){return d[x]<d[y]?x:y;} void ST(){ for(int k=1;(1<<k)<=dfn;++k) for(int i=1;i<=dfn-(1<<k)+1;++i) st[k][i]=gmd(st[k-1][i],st[k-1][i+(1<<k-1)]); } void swap(int&x,int&y){int t=x;x=y;y=t;} int lca(int x,int y){ int l=L[x],r=L[y]; if(l>r)swap(l,r); int k=log2(r-l+1); return gmd(st[k][l],st[k][r-(1<<k)+1]); } int v[N],ti; bool chk(int x,int y,int p){ return L[x]<=L[p]&&L[p]<=R[x]&&L[p]<=L[y]&&L[y]<=R[p]; } ll ask1(int x,int y){ if(d[x]>d[y])swap(x,y); int F=lca(x,y); ll ans=T.ask(RT[f[F]],RT[y],d[F]-1,0,n).v; ++ti; for(int i=x;i!=F;i=f[i])if(v[a[i]]!=ti){ v[a[i]]=ti; bool ff=1; for(int j:vec[a[i]]) if(chk(F,y,j)){ff=0;break;} ans+=ff; } return ans; } ll calc(int A,int B,node t){// i∈[1,A],i∈(A,B] return (d[A]+d[B]+2)*sum[A][0]-2*sum[A][1]-d[A]+ (d[A]*t.v-t.pd)*(d[B]+1)-d[A]*t.d+t.pdxd; } ll ask2(int A,int B){ if(d[A]>d[B])swap(A,B); int F=lca(A,B); node FA=T.ask(RT[f[F]],RT[A],d[F]-1,0,n), FB=T.ask(RT[f[F]],RT[B],d[F]-1,0,n); ll ans=calc(f[F],B,FB) // x∈[1,lca],y∈[1,B] +calc(f[F],A,FA); // x∈[1,A],y∈[1,lca] ans-=2*(d[F]*sum[f[F]][0]-sum[f[F]][1])-(d[F]-1);// - x,y∈[1,lca) ans+=(d[A]-d[F]+1)*((d[B]+1)*FB.v-FB.d);// i∈[lca,B] list<int>sta; for(int i=A;i!=F;i=f[i])sta.push_back(i); ++ti; while(!sta.empty()){// i∈(lca,A] int i=sta.back();sta.pop_back(); if(v[a[i]]!=ti){ v[a[i]]=ti; int mi=d[B]+1; for(int j:vec[a[i]]) if(chk(F,B,j)&&d[j]<mi)mi=d[j]; ans+=ll(d[A]-d[i]+1)*(mi-d[F]); } } return ans; } unsigned int SA,SB,SC; unsigned int rng61(){SA^=SA<<16;SA^=SA>>5;SA^=SA<<1;unsigned int t=SA;SA=SB;SB=SC;SC^=t^SA;return SC;} void solve(){ int q,p,x,y; scanf("%d%d%u%u%u%d",&n,&p,&SA,&SB,&SC,&q); for(int i=2;i<=n;++i) e[f[i]=i>p?rng61()%(i-1)+1:i-1].push_back(i); for(int i=1;i<=n;++i)vec[a[i]=rng61()%n+1].push_back(i); T.build(RT[0],0,n); d[1]=1,dfs(1);ST(); while(q--) scanf("%d%d%d",&p,&x,&y), printf("%lld\n",p==1?ask1(x,y):ask2(x,y)); dfn=T.sz=0; for(int i=1;i<=n;++i) vec[i].clear(),e[i].clear(), RT[i]=v[i]=b[i]=0; } int main(){ int T;scanf("%d",&T); while(T--)solve(); }
-
12021-07-18 21:41:03@
#include<bits/stdc++.h> using std::list; typedef long long ll; const int N=100011; int n,a[N];list<int>vec[N],e[N]; int RT[N]; struct node{ ll v,pd,d,pdxd;// Σ1,Σdep[pre],Σdep[i],Σdep[pre]×dep[i] node operator+(const node&t){return node{v+t.v,pd+t.pd,d+t.d,pdxd+t.pdxd};} node operator-(const node&t){return node{v-t.v,pd-t.pd,d-t.d,pdxd-t.pdxd};} }; struct prt{ int sz,ls[N*20],rs[N*20]; node s[N*20]; void build(int&x,int l,int r){ s[x=++sz]=node{0,0,0,0}; if(l==r)return; int m=l+r>>1; build(ls[x],l,m);build(rs[x],m+1,r); } void ins(int&x,int pre,int p,int l,int r,node v){ s[x=++sz]=s[pre]+v; if(l==r)return; ls[x]=ls[pre],rs[x]=rs[pre]; int m=l+r>>1; if(p<=m)ins(ls[x],ls[pre],p,l,m,v); else ins(rs[x],rs[pre],p,m+1,r,v); } node ask(int x,int y,int R,int l,int r){ if(r<=R)return s[y]-s[x]; int m=l+r>>1; node ans=ask(ls[x],ls[y],R,l,m); return R>m?ans+ask(rs[x],rs[y],R,m+1,r):ans; } }T; int L[N],R[N],dfn,st[20][N*2]; int f[N],d[N],pre[N],b[N];ll sum[N][2]; void dfs(int x){ st[0][L[x]=++dfn]=x; pre[x]=b[a[x]],b[a[x]]=x; T.ins(RT[x],RT[f[x]],pre[x],0,n,node{ 1,d[pre[x]],d[x],1ll*d[pre[x]]*d[x] }); sum[x][0]=d[x]-d[pre[x]]+sum[f[x]][0]; sum[x][1]=1ll*(d[x]-d[pre[x]])*d[x]+sum[f[x]][1]; for(int to:e[x])d[to]=d[x]+1,dfs(to),st[0][++dfn]=x; R[x]=dfn; b[a[x]]=pre[x]; } int gmd(int x,int y){return d[x]<d[y]?x:y;} void ST(){ for(int k=1;(1<<k)<=dfn;++k) for(int i=1;i<=dfn-(1<<k)+1;++i) st[k][i]=gmd(st[k-1][i],st[k-1][i+(1<<k-1)]); } void swap(int&x,int&y){int t=x;x=y;y=t;} int lca(int x,int y){ int l=L[x],r=L[y]; if(l>r)swap(l,r); int k=log2(r-l+1); return gmd(st[k][l],st[k][r-(1<<k)+1]); } int v[N],ti; bool chk(int x,int y,int p){ return L[x]<=L[p]&&L[p]<=R[x]&&L[p]<=L[y]&&L[y]<=R[p]; } ll ask1(int x,int y){ if(d[x]>d[y])swap(x,y); int F=lca(x,y); ll ans=T.ask(RT[f[F]],RT[y],d[F]-1,0,n).v; ++ti; for(int i=x;i!=F;i=f[i])if(v[a[i]]!=ti){ v[a[i]]=ti; bool ff=1; for(int j:vec[a[i]]) if(chk(F,y,j)){ff=0;break;} ans+=ff; } return ans; } ll calc(int A,int B,node t){// i∈[1,A],i∈(A,B] return (d[A]+d[B]+2)*sum[A][0]-2*sum[A][1]-d[A]+ (d[A]*t.v-t.pd)*(d[B]+1)-d[A]*t.d+t.pdxd; } ll ask2(int A,int B){ if(d[A]>d[B])swap(A,B); int F=lca(A,B); node FA=T.ask(RT[f[F]],RT[A],d[F]-1,0,n), FB=T.ask(RT[f[F]],RT[B],d[F]-1,0,n); ll ans=calc(f[F],B,FB) // x∈[1,lca],y∈[1,B] +calc(f[F],A,FA); // x∈[1,A],y∈[1,lca] ans-=2*(d[F]*sum[f[F]][0]-sum[f[F]][1])-(d[F]-1);// - x,y∈[1,lca) ans+=(d[A]-d[F]+1)*((d[B]+1)*FB.v-FB.d);// i∈[lca,B] list<int>sta; for(int i=A;i!=F;i=f[i])sta.push_back(i); ++ti; while(!sta.empty()){// i∈(lca,A] int i=sta.back();sta.pop_back(); if(v[a[i]]!=ti){ v[a[i]]=ti; int mi=d[B]+1; for(int j:vec[a[i]]) if(chk(F,B,j)&&d[j]<mi)mi=d[j]; ans+=ll(d[A]-d[i]+1)*(mi-d[F]); } } return ans; } unsigned int SA,SB,SC; unsigned int rng61(){SA^=SA<<16;SA^=SA>>5;SA^=SA<<1;unsigned int t=SA;SA=SB;SB=SC;SC^=t^SA;return SC;} void solve(){ int q,p,x,y; scanf("%d%d%u%u%u%d",&n,&p,&SA,&SB,&SC,&q); for(int i=2;i<=n;++i) e[f[i]=i>p?rng61()%(i-1)+1:i-1].push_back(i); for(int i=1;i<=n;++i)vec[a[i]=rng61()%n+1].push_back(i); T.build(RT[0],0,n); d[1]=1,dfs(1);ST(); while(q--) scanf("%d%d%d",&p,&x,&y), printf("%lld\n",p==1?ask1(x,y):ask2(x,y)); dfn=T.sz=0; for(int i=1;i<=n;++i) vec[i].clear(),e[i].clear(), RT[i]=v[i]=b[i]=0; } int main(){ int T;scanf("%d",&T); while(T--)solve(); }
-
-12020-04-30 18:03:27@
#include<cstdio> #include<algorithm> #include<stack> using namespace std;const int N=1e5+10;const int E=20*N;typedef long long ll;typedef unsigned int uit; int n;int m;int p;int v[2*N];int x[2*N];int ct;int al[N];int pre[N];int dep[N];int a[N];bool book[N]; stack <int> s[N];int fa[N];int T; struct data//主席树强行维护信息 { int v0;ll v1;ll v2;ll v3;data(int a=0,ll b=0,ll c=0,ll d=0){v0=a;v1=b;v2=c;v3=d;} friend data operator +(data a,data b){return data(a.v0+b.v0,a.v1+b.v1,a.v2+b.v2,a.v3+b.v3);} friend data operator -(data a,data b){return data(a.v0-b.v0,a.v1-b.v1,a.v2-b.v2,a.v3-b.v3);} }; struct answ//树上前缀和 { ll v1;ll v2;answ(ll a=0,ll b=0){v1=a;v2=b;} friend answ operator +(answ a,answ b){return answ(a.v1+b.v1,a.v2+b.v2);} friend answ operator -(answ a,answ b){return answ(a.v1-b.v1,a.v2-b.v2);} }val[N]; struct per_linetree//主席树的板子 { data v[E];int s[E][2];int root[N];int ct; inline void modify(int p1,int p2,int l,int r,const int& pos,const data& pl) { v[p2]=v[p1]+pl;if(r-l==1){s[p2][0]=0;s[p2][1]=0;return;}int mid=(l+r)/2; if(pos<=mid){s[p2][1]=s[p1][1];modify(s[p1][0],s[p2][0]=++ct,l,mid,pos,pl);} else {s[p2][0]=s[p1][0];modify(s[p1][1],s[p2][1]=++ct,mid,r,pos,pl);} } inline data query(int p,int l,int r,int dl,int dr) { if(p==0||dl==l&&dr==r){return v[p];}int mid=(l+r)/2;data ret; if(dl<mid)ret=ret+query(s[p][0],l,mid,dl,min(dr,mid)); if(mid<dr)ret=ret+query(s[p][1],mid,r,max(dl,mid),dr);return ret; } inline void cmodify(int p1,int p2,int pos,const data& pl) {modify(root[p1],root[p2]=++ct,0,n+1,pos+1,pl);} inline data cquery(int p1,int p2,int l,int r) {return query(root[p2],0,n+1,l+1,r+1)-query(root[p1],0,n+1,l+1,r+1);} inline void clear(){ct=1;} }plt; struct per_array//可持久化数组,还是主席树的板子 { int v[E];int s[E][2];int root[N];int ct; inline void modify(int p1,int p2,int l,int r,const int& pos,const int & pl) { v[p2]=pl;if(r-l==1){s[p2][0]=0;s[p2][1]=0;return;}int mid=(l+r)/2; if(pos<=mid){s[p2][1]=s[p1][1];modify(s[p1][0],s[p2][0]=++ct,l,mid,pos,pl);} else {s[p2][0]=s[p1][0];modify(s[p1][1],s[p2][1]=++ct,mid,r,pos,pl);} } inline int query(int p,int l,int r,int pos) { if(p==0||r-l==1){return v[p];}int mid=(l+r)/2; if(pos<=mid){return query(s[p][0],l,mid,pos);} else {return query(s[p][1],mid,r,pos);} } inline void cmodify(int p1,int p2,const int& pos,const int& pl) {modify(root[p1],root[p2]=++ct,0,n+1,pos+1,pl);} inline int cquery(int p,int pos){return query(root[p],0,n+1,pos+1);} inline void clear(){ct=1;} }pa; inline void add(int u,int V){v[++ct]=V;x[ct]=al[u];al[u]=ct;} inline void dfs(int u,int f)//dfs建树形主席树,顺手处理出pre和树上前缀和 { pre[u]=s[a[u]].empty()?0:s[a[u]].top();s[a[u]].push(u);int dp=dep[pre[u]]; plt.cmodify(f,u,dp,data(1,dep[u],dp,(ll)dp*dep[u])); pa.cmodify(f,u,a[u],u);fa[u]=f; val[u]=val[f]+answ(dep[u]-dp,(ll)(dep[u]-dp)*(-2*dep[u]+2)-1); for(int i=al[u];i;i=x[i]){dep[v[i]]=dep[u]+1;dfs(v[i],u);} s[a[u]].pop(); } inline int query1(int u,int v) { if(dep[u]>dep[v])swap(u,v);int lc=u;int lc1=v;//暴力找lca for(;lc1>p;lc1=fa[lc1])book[lc1]=true; for(;lc>p;lc=fa[lc])if(book[lc])goto ed1; lc=(dep[lc]<dep[lc1])?lc:lc1;ed1:; for(int x=v;x>p;x=fa[x])book[x]=false; int ans=plt.cquery(fa[lc],v,-1,dep[lc]-1).v0;//提取长链信息 for(int x=u;x!=lc;x=fa[x]) if(dep[pre[x]]<dep[lc]&&dep[pa.cquery(v,a[x])]<dep[lc])ans++;//暴力插入短链 return ans; } inline ll subquery(int l,int r)//操作2的序列问题 { ll L=dep[l];ll R=dep[r];data ret=(l!=r)?plt.cquery(l,r,-1,dep[l]):data();//无脑考虑贡献即可 return val[l].v1*(L+R)+val[l].v2+ret.v0*L*(R+1)-L*ret.v1-(R+1)*ret.v2+ret.v3; } inline ll query2(int u,int v)//操作2 { if(dep[u]>dep[v])swap(u,v);int lc=u;int lc1=v;//还是暴力找lca for(;lc1>p;lc1=fa[lc1])book[lc1]=true; for(;lc>p;lc=fa[lc])if(book[lc])goto ed1; lc=(dep[lc]<dep[lc1])?lc:lc1;ed1:; for(int x=v;x>p;x=fa[x])book[x]=false; ll ret=subquery(lc,v)+subquery(lc,u)-subquery(lc,lc);//处理直路径 if(lc==u)return ret;data tr=plt.cquery(lc,v,-1,dep[lc]-1);//弯路径的长链贡献,主席树查一发即可 ret+=(dep[u]-dep[lc])*((ll)tr.v0*(dep[v]+1)-tr.v1)+(ll)(dep[v]-dep[lc])*(dep[u]-dep[lc]);//记得加上lca for(int x=u;x!=lc;x=fa[x]) { if(dep[pre[x]]>=dep[lc]){continue;}//如果数不到这个点就跳过 int pr=pa.cquery(v,a[x]); if(dep[pr]<dep[lc]){ret+=(ll)(dep[v]-dep[lc])*(dep[u]-dep[x]+1);continue;}//如果一定可以插入成功就直接算贡献 for(;dep[pre[pr]]>=dep[lc];pr=pre[pr]);if(dep[pr]==dep[lc])continue;//跳pre找第一次出现的点 ret+=(ll)(dep[pr]-dep[lc]-1)*(dep[u]-dep[x]+1);//计算贡献 }return ret; } namespace Maker//生成器代码,直接粘就行了 { uit SA,SB,SC; uit rng61(){SA^=SA<<16;SA^=SA>>5;SA^=SA<<1;uit t=SA;SA=SB;SB=SC;SC^=t^SA;return SC;} void gen() { scanf("%d%d%u%u%u",&n,&p,&SA,&SB,&SC); for(int i=2;i<=p;i++)add(i-1,i); for(int i=p+1;i<=n;i++)add(rng61()%(i-1)+1,i); for(int i=1;i<=n;i++)a[i]=rng61()%n+1; } } inline void solve() { Maker::gen();scanf("%d",&m);dep[1]=1;dfs(1,0); for(int i=1,t,l,r;i<=m;i++) {scanf("%d%d%d",&t,&l,&r);printf("%lld\n",(t==1)?query1(l,r):query2(l,r));} } inline void clear(){plt.clear();pa.clear();for(int i=1;i<=n;i++)al[i]=0;ct=0;} int main(){scanf("%d",&T);for(int z=1;z<=T;z++){solve();clear();}return 0;}
- 1
信息
- ID
- 2048
- 难度
- 8
- 分类
- (无)
- 标签
- 递交数
- 42
- 已通过
- 13
- 通过率
- 31%
- 被复制
- 2
- 上传者