bzoj4012(動態點分治+卡常數)
阿新 • • 發佈:2019-02-05
這是一種型別的動態點分治
動態點分治,關鍵還是要在均攤n的空間複雜度記憶體下所有東西。這個就要充分利用stl,比如vector
每一個點存以這個點為根點分治的資訊。
對於詢問一個點的路徑時,就是沿著點分治樹,不斷朝fa走,每走一層統計一下,因為分治樹可以保證在log層內,時間複雜度同階
卡常數
無優化:43848ms
優化一:取模優化(x-=mod 代替 % ) + 迴圈展開+ 一部分inline :43612ms
第三次:將i++改為++i:速度稍減慢,dfs(int &u)佔位符加速也沒有體現出來
優化不下去了
#include<cmath> #include<cstring> #include<cstdlib> #include<algorithm> #include<cstdio> #include<queue> #include<vector> #include<utility> #define fi first #define se second #define pii pair<int,int> #define MK(a,b) make_pair((a),(b)) using namespace std; typedef long long ll; const int N=150005; inline int read() { int ans,f=1;char ch; while ((ch=getchar())<'0'||ch>'9') if (ch=='-') f=-1;ans=ch-'0'; while ((ch=getchar())>='0'&&ch<='9') ans=ans*10+ch-'0'; return ans*f; } int n,Q,A;ll ans; int U,L,R; ///////////////////// struct bian { int to[N*2],pre[N*2],dis[N*2],head[N],tot; void addedge(int u,int v,int d) { to[++tot]=v;pre[tot]=head[u];head[u]=tot;dis[tot]=d; } }e; ////////////////////// int age[N],fa[N];ll dis[N]; struct aa { int num; vector< pair<int,pair<int,int> > >a; vector< pair<int,ll> > ch[3]; int f(int u) { int l=0,r=a.size()-1,mid,ans; while (l<=r) { mid=(l+r)>>1; if (a[mid].fi>=u) ans=mid,r=mid-1; else l=mid+1; } return ans; } int dis(int u) { return a[f(u)].se.se; } int id(int u) { return a[f(u)].se.fi; } void init() { sort(a.begin(),a.end()); for (int i=0;i<num;i++) { sort(ch[i].begin(),ch[i].end()); int sz=ch[i].size(); for (int j=1;j<sz;j++) ch[i][j].se+=ch[i][j-1].se; } } ll query(int u,int up) { int tid=id(u);ll tdis=dis(u),ans=0; for (int i=0;i<num;i++) if (tid!=i) { int pos=upper_bound(ch[i].begin(),ch[i].end(),MK(up,(ll)(1e16)))-ch[i].begin(); if (pos==0) continue; ans+=(ll)pos*tdis; ans+=ch[i][pos-1].se; } return ans; } }tt[N]; ///////////// int size[N],sum,mi,rt; bool b[N]; void get_size(int u,int fat) { int v;size[u]=1; for (int i=e.head[u];i;i=e.pre[i]) { v=e.to[i]; if (!b[v]&&v!=fat) { get_size(v,u); size[u]+=size[v]; } } } void get_rt(int u,int fat) { int v,mx=sum-size[u]; for (int i=e.head[u];i;i=e.pre[i]) { v=e.to[i]; if (!b[v]&&v!=fat) { get_rt(v,u); mx=max(mx,size[v]); } } if (mx<mi) rt=u,mi=mx; } queue<int> q; void dfs2(int u,int fat,int d) { int v; dis[u]=d;q.push(u); for (int i=e.head[u];i;i=e.pre[i]) { v=e.to[i]; if (!b[v]&&v!=fat) dfs2(v,u,d+e.dis[i]); } } void work(int u) { int v,&num=tt[u].num; tt[u].a.push_back(MK(u,MK(-1,0))); for (int i=e.head[u];i;i=e.pre[i]) { v=e.to[i]; if (!b[v]) { dfs2(v,u,e.dis[i]); while (!q.empty()) { v=q.front();q.pop(); tt[u].a.push_back(MK(v,MK(num,dis[v]))); tt[u].ch[num].push_back(MK(age[v],dis[v])); } num++; } } tt[u].init(); } void dfs(int u,int fat) { get_size(u,0);sum=size[u];mi=1e7; get_rt(u,0);u=rt; b[u]=true;fa[u]=fat;work(u); for (int i=e.head[u];i;i=e.pre[i]) if (!b[e.to[i]]) dfs(e.to[i],u); } /////////////////////////////////////////// void init() { n=read(),Q=read(),A=read(); for (int i=1;i<=n;i++) age[i]=read(); int xx,yy,zz; for (int i=1;i<n;i++) { xx=read(),yy=read(),zz=read(); e.addedge(xx,yy,zz); e.addedge(yy,xx,zz); } dfs(1,0); } ll query(int u,int up) { if (up<0) return 0; ll ans=0; while (u) { if (age[u]<=up) ans+=tt[u].dis(U); ans+=tt[u].query(U,up),u=fa[u]; } return ans; } int main() { init(); for (int i=1;i<=Q;i++) { U=read(),L=read(),R=read(); L=(L+ans)%A,R=(R+ans)%A; if (L>R) swap(L,R); ans= query(U,R)- query(U,L-1); printf("%lld\n",ans); ans=ans%A; } return 0; }