传送门:bzoj4012
这题码+调试就花了一中午和一下午。。。最后发现问题都是有地方没开 l o n g l o n g long \ long long longTAT。。。
法2的代码比较有技巧性(还不太熟。
法1(点分树):
首先点分治处理出 v : v: v:每个重心到其所管辖子树中每个点的距离,压进vector后按年龄排序,转成距离的前缀和, f v : fv: fv:该点点分树中的父亲结点到这颗子树每个点的距离,同样压进vector后排序求前缀和(容斥用)
暴力跳点分树,每层二分找到需要的区间处理即可。细节可以自己再想一下。
法2(树剖+主席树):
注意到 d i s ( u , v ) = d e p ( u ) + d e p ( v ) − 2 × d e p ( L C A ( u , v ) ) dis(u,v)=dep(u)+dep(v)-2\times dep(LCA(u,v)) dis(u,v)=dep(u)+dep(v)−2×dep(LCA(u,v)),于是点之间的关系转成了分别处理每个点对于答案的贡献。
某个年龄区间的 d e p ( v ) dep(v) dep(v)可以排序+前缀和处理。关键问题在于如何快速求出 ∑ d e p ( L C A ( u , v ) ) \sum dep(LCA(u,v)) ∑dep(LCA(u,v))。
采用一种 O ( n l o g 2 n ) O(nlog^2n) O(nlog2n)的方法:把每个点到根路径上的所有边覆盖次数+1, ∑ d e p ( L C A ( u , v ) ) \sum dep(LCA(u,v)) ∑dep(LCA(u,v))就是 u u u到根路径上的每条边的边权 × \times ×覆盖次数。
由于每次查询的是一段年龄连续的区间,可以建立主席树,将点按年龄排序后逐个加入。
注意:点数太多,需要标记永久化。
点分树:
#include
#define pb push_back
#define mid ((L+R)>>1)
using namespace std;
const int N=15e4+10;
typedef long long ll;
int n,m,A,ag[N];ll ans;
int head[N],to[N<<1],nxt[N<<1],w[N<<1],tot;
int sz[N],f[N],son[N],top[N],dep[N],dis[N];
clock_t stt,edd;
char cp,OS[100];
template<class yyy>inline void rd(yyy &x)
{
cp=getchar();x=0;
for(;!isdigit(cp);cp=getchar());
for(;isdigit(cp);cp=getchar()) x=(x<<3)+(x<<1)+(cp^48);
}
template<class yyy>inline void ot(yyy x)
{
int re=0;for(;(!re)||(x);x/=10) OS[++re]='0'+x%10;
for(OS[0]='\n';~re;--re) putchar(OS[re]);
}
inline void lk(int u,int v,int vv)
{to[++tot]=v;nxt[tot]=head[u];head[u]=tot;w[tot]=vv;}
void dfs(int x)
{
sz[x]=1;
for(int j,i=head[x];i;i=nxt[i]){
j=to[i];if(j==f[x]) continue;
f[j]=x;dep[j]=dep[x]+1;dis[j]=dis[x]+w[i];dfs(j);
sz[x]+=sz[j];if(sz[j]>sz[son[x]]) son[x]=j;
}
}
void dfss(int x,int tpo)
{
top[x]=tpo;if(!son[x]) return;dfss(son[x],tpo);
for(int j,i=head[x];i;i=nxt[i]){
j=to[i];if(j==f[x] || j==son[x]) continue;
dfss(j,j);
}
}
inline int LCA(int x,int y){for(;top[x]!=top[y];x=f[top[x]]) if(dep[top[x]]<dep[top[y]]) swap(x,y);
return dep[x]<dep[y]?x:y;}
inline int dist(int x,int y){
return dis[x]+dis[y]-(dis[LCA(x,y)]<<1);}
namespace ds{
int f[N],mx[N],MN,S,rt,vs[N],b;
struct P{
int yr;ll d;
P(int yr_=0,ll d_=0):yr(yr_),d(d_){};
bool operator<(const P&ky)const{return yr<ky.yr;}
bool operator <=(const P&ky)const{return yr<=ky.yr;}
};
vector<P>v[N],fv[N];
void getrt(int x,int fr)
{
sz[x]=1;mx[x]=0;
for(int j,i=head[x];i;i=nxt[i]){
j=to[i];if(j==fr || vs[j]) continue;
getrt(j,x);sz[x]+=sz[j];mx[x]=max(mx[x],sz[j]);
}
mx[x]=max(mx[x],S-sz[x]);
if(mx[x]<MN) {MN=mx[x];rt=x;}
}
void dfs(int x,int fr,int ds)
{
v[b].pb(P(ag[x],ds));
for(int j,i=head[x];i;i=nxt[i]){
j=to[i];if(j==fr || vs[j]) continue;
dfs(j,x,ds+w[i]);
}
}
void dfss(int x,int fr,int ds)
{
fv[b].pb(P(ag[x],ds));
for(int j,i=head[x];i;i=nxt[i]){
j=to[i];if(j==fr || vs[j]) continue;
dfss(j,x,ds+w[i]);
}
}
void build(int x)
{
int i,j,k,sq=S;vs[x]=1;b=x;dfs(x,0,0);
sort(v[x].begin(),v[x].end());j=v[x].size();
for(i=1;i<j;++i) v[x][i].d+=v[x][i-1].d;
for(int j,i=head[x];i;i=nxt[i]){
j=to[i];if(vs[j]) continue;S=(sz[j]>sz[x])?(sq-sz[x]):sz[j];MN=n+1;
getrt(j,x);f[rt]=x;b=rt;dfss(j,x,w[i]);
sort(fv[rt].begin(),fv[rt].end());j=fv[rt].size();
for(k=1;k<j;++k) fv[rt][k].d+=fv[rt][k-1].d;build(rt);
}
}
inline ll cala(int l,int r,int dd)
{
int x=v[b].size(),y=-1,L=0,R=v[b].size()-1;
for(;L<=R;)
v[b][mid].yr>=l?(R=(x=mid)-1):(L=mid+1);
for(L=0,R=v[b].size()-1;L<=R;)
v[b][mid].yr<=r?(L=(y=mid)+1):(R=mid-1);
if(x>y) return 0LL;
return v[b][y].d-(x?v[b][x-1].d:0)+(ll)(y-x+1)*dd;
}
inline ll calb(int l,int r,int dd)
{
int x=fv[b].size(),y=-1,L=0,R=fv[b].size()-1;
for(;L<=R;)
fv[b][mid].yr>=l?(R=(x=mid)-1):(L=mid+1);
for(L=0,R=fv[b].size()-1;L<=R;)
fv[b][mid].yr<=r?(L=(y=mid)+1):(R=mid-1);
if(x>y) return 0LL;
return fv[b][y].d-(x?fv[b][x-1].d:0)+(ll)(y-x+1)*dd;
}
inline void query(int x,int l,int r)
{
b=x;ans=cala(l,r,0);int dd,ori=x;
for(;f[x];x=b){
dd=dist(ori,f[x]);
b=x;ans-=calb(l,r,dd);
b=f[x];ans+=cala(l,r,dd);
}
}
}
int main(){
using namespace ds;
int i,j,k,x,y,z;
rd(n);rd(m);rd(A);
for(i=1;i<=n;++i) rd(ag[i]);
for(i=1;i<n;++i){
rd(x);rd(y);rd(z);lk(x,y,z);lk(y,x,z);
}
dep[1]=1;dfs(1);dfss(1,1);
MN=n+1;S=n;getrt(1,0);
build(rt);
for(;m;--m){
rd(x);rd(y);rd(z);y=(ans+y)%A;z=(ans+z)%A;
query(x,min(y,z),max(y,z));ot(ans);
}
return 0;
}
树剖+主席树
#include
#define mid ((l+r)>>1)
using namespace std;
const int N=15e4+10,M=2e7+10;
typedef long long ll;
int n,m,A,vl[N],bl[N],num,df[N],dfn;ll ans;
int head[N],to[N<<1],nxt[N<<1],w[N<<1],tot,dis[N];
int sz[N],f[N],son[N],top[N],dep[N],rt[N],cnt;
int ls[M],rs[M],st[M];ll ss[M],qz[N];
struct P{
int id,v;
bool operator<(const P&ky)const{return v<ky.v;}
}q[N];
clock_t stt,edd;
char cp,OS[100];
template<class yyy>inline void rd(yyy &x)
{
cp=getchar();x=0;
for(;!isdigit(cp);cp=getchar());
for(;isdigit(cp);cp=getchar()) x=(x<<3)+(x<<1)+(cp^48);
}
template<class yyy>inline void ot(yyy x)
{
int re=0;for(;(!re)||(x);x/=10) OS[++re]='0'+x%10;
for(OS[0]='\n';~re;--re) putchar(OS[re]);
}
inline void lk(int u,int v,int vv)
{to[++tot]=v;nxt[tot]=head[u];head[u]=tot;w[tot]=vv;}
void dfs(int x)
{
sz[x]=1;
for(int j,i=head[x];i;i=nxt[i]){
j=to[i];if(j==f[x]) continue;
bl[j]=w[i];f[j]=x;dep[j]=dep[x]+1;dis[j]=dis[x]+w[i];dfs(j);
sz[x]+=sz[j];if(sz[j]>sz[son[x]]) son[x]=j;
}
}
void dfss(int x,int tpo)
{
top[x]=tpo;df[x]=++dfn;vl[dfn]=bl[x];
if(!son[x]) return;dfss(son[x],tpo);
for(int j,i=head[x];i;i=nxt[i]){
j=to[i];if(j==f[x] || j==son[x]) continue;
dfss(j,j);
}
}
void ad(int pr,int &k,int l,int r,int L,int R)
{
if(k==pr){k=++cnt;st[k]=st[pr];ss[k]=ss[pr];ls[k]=ls[pr];rs[k]=rs[pr];}
if(L==l && r==R) {st[k]++;return;}ss[k]+=(vl[R]-vl[L-1]);
if(L<=mid) ad(ls[pr],ls[k],l,mid,L,min(R,mid));
if(R>mid) ad(rs[pr],rs[k],mid+1,r,max(L,mid+1),R);
}
ll ask(int k,int l,int r,int L,int R)
{
if(!k) return 0LL;
if(L==l && r==R) return ss[k]+(ll)st[k]*(vl[r]-vl[l-1]);
ll re=(ll)(vl[R]-vl[L-1])*st[k];
if(L<=mid) re+=ask(ls[k],l,mid,L,min(R,mid));
if(R>mid) re+=ask(rs[k],mid+1,r,max(L,mid+1),R);
return re;
}
inline void query(int x,int L,int R)
{
if(L>R) {ans=0LL;return;}ans=qz[R]-qz[L-1]+(ll)dis[x]*(R-L+1);
L=rt[L-1];R=rt[R];
for(;x;x=f[top[x]])
ans-=((ask(R,1,n,df[top[x]],df[x])-ask(L,1,n,df[top[x]],df[x]))<<1);
}
inline int dn(int x)
{
int l=1,r=n,re=n+1;
for(;l<=r;) q[mid].v>=x?(r=(re=mid)-1):(l=mid+1);
return re;
}
inline int up(int x)
{
int l=1,r=n,re=-1;
for(;l<=r;) q[mid].v<=x?(l=(re=mid)+1):(r=mid-1);
return re;
}
int main(){
int i,j,k,x,y,z;
rd(n);rd(m);rd(A);vl[0]=0;qz[0]=0LL;
for(i=1;i<=n;++i) rd(q[i].v),q[i].id=i;sort(q+1,q+n+1);
for(i=1;i<n;++i){rd(x);rd(y);rd(z);lk(x,y,z);lk(y,x,z);}
dep[1]=1;dfs(1);dfss(1,1);for(i=1;i<=n;++i) vl[i]+=vl[i-1],qz[i]=qz[i-1]+dis[q[i].id];
for(i=1;i<=n;++i)
for(rt[i]=rt[i-1],x=q[i].id;x;x=f[top[x]]) ad(rt[i-1],rt[i],1,n,df[top[x]],df[x]);
for(;m;--m){
rd(x);rd(y);rd(z);y=(ans+y)%A;z=(ans+z)%A;if(y>z) swap(y,z);
query(x,dn(y),up(z));ot(ans);
}
return 0;
}