http://www.lydsy.com/JudgeOnline/problem.php?id=4012
两点间距离:深度之和-2×LCA深度
http://blog.csdn.net/mima_reincarnation/article/details/54024494
ORZ16年我就会的东西现在怎么忘没了。。。那题是离线排序做,那么对于这题用可持久化线段树来维护树链剖分就可以了。
#include
#include
#define gm 300001
using namespace std;
typedef long long ll;
struct Istream
{
static const size_t str=1<<16;
char buf[str],*s,*t;
Istream():buf(),s(),t(){}
char get()
{
return (s==t)?(t=buf+fread(s=buf,1,str,stdin),*s++):(*s++);
}
template<typename int_t>
Istream& operator>> (int_t &x)
{
x=0; register char c;
do c=get(); while(c<'0'||c>'9');
while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-'0',c=get();
return *this;
}
}cin;
struct Ostream
{
static const size_t str=1<<16;
char buf[str],*s,*t;
Ostream():buf(),s(buf),t(buf+str){}
~Ostream(){fwrite(buf,1,s-buf,stdout);}
void put(char c)
{
(s==t)?(fwrite(s=buf,1,str,stdout),*s++=c):(*s++=c);
}
template<typename int_t>
Ostream& operator<< (int_t x)
{
if(!x) return operator<<('0');
int a[22],t=1;
while(x) a[t++]=x%10,x/=10;
while(--t) put(a[t]+'0');
return *this;
}
Ostream& operator<< (char c){return put(c),*this;}
}cout;
const char endl='\n';
int n,q,a;
struct pnt
{
int pos,age;
operator int() const {return age;}
}p[gm];
struct e
{
int t;
e *n;
int c;
e(int t,e *n,int c):t(t),n(n),c(c){}
}*f[gm];
int fa[gm],sz[gm],dep[gm],son[gm],len[gm],top[gm],dfn[gm],pre[gm],ct;
ll we[gm];
void dfs1(int x=1)
{
sz[x]=1;
for(e *i=f[x];i;i=i->n)
{
if(fa[x]==i->t) continue;
fa[i->t]=x;
len[i->t]=i->c;
dep[i->t]=dep[x]+i->c;
dfs1(i->t);
if(sz[i->t]>sz[son[x]]) son[x]=i->t;
sz[x]+=sz[i->t];
}
}
void dfs2(int x=1)
{
dfn[x]=++ct; pre[ct]=pre[ct-1]+len[x];
top[x]=(x==son[fa[x]])?top[fa[x]]:x;
if(son[x]) dfs2(son[x]);
for(e *i=f[x];i;i=i->n)
{
if(fa[x]==i->t||son[x]==i->t) continue;
dfs2(i->t);
}
}
struct node
{
node *l,*r;
int mark,clk,tot;
ll sum;
node(int tot):l(),r(),mark(),clk(ct),tot(tot),sum(){}
node(const node &x):l(x.l),r(x.r),mark(x.mark),clk(ct),tot(x.tot),sum(x.sum){}
void cast()
{
++mark; sum+=tot;
}
void up()
{
sum=ll(mark)*tot;
if(l) sum+=l->sum;
if(r) sum+=r->sum;
}
}*rt[gm];
int x,y;
void insert(node *&o,int l=1,int r=n)
{
if(!o) o=new node(pre[r]-pre[l-1]);
else if(o->clk!=ct) o=new node(*o);
if(x<=l&&r<=y) {o->cast(); return;}
int mid=l+r>>1;
if(x<=mid) insert(o->l,l,mid);
if(midr,mid+1,r);
o->up();
}
ll query(node *o,int l=1,int r=n,int cnt=0)
{
if(!o) return ll(pre[min(r,y)]-pre[max(l,x)-1])*cnt;
if(x<=l&&r<=y) return o->sum+ll(o->tot)*cnt;
cnt+=o->mark;
int mid=l+r>>1;
ll res=0;
if(x<=mid) res+=query(o->l,l,mid,cnt);
if(midr,mid+1,r,cnt);
return res;
}
void jump(int no)
{
int b=p[no].pos;
++ct; rt[no]=rt[no-1];
while(b)
{
x=dfn[top[b]],y=dfn[b];
insert(rt[no]);
b=fa[top[b]];
}
}
ll get(int b,node *h)
{
ll res=0;
while(b)
{
x=dfn[top[b]],y=dfn[b];
res+=query(h);
b=fa[top[b]];
}
return res;
}
ll ans=0;
int main()
{
cin>>n>>q>>a;
for(int i=1;i<=n;++i)
{
p[i].pos=i;
cin>>p[i].age;
}
sort(p+1,p+n+1);
for(int i=1;iint u,v,c; cin>>u>>v>>c;
f[u]=new e(v,f[u],c); f[v]=new e(u,f[v],c);
}
dfs1(),dfs2(),ct=0;
for(int i=1;i<=n;++i) we[i]=we[i-1]+dep[p[i].pos];
for(int i=1;i<=n;++i) jump(i);
for(int i=1;i<=q;++i)
{
int u; ll b,c; cin>>u>>b>>c;
int l=min((b+ans)%a,(c+ans)%a),r=max((b+ans)%a,(c+ans)%a);
l=lower_bound(p+1,p+n+1,l)-p,r=upper_bound(p+1,p+n+1,r)-p;
if(l==r) ans=0;
else ans=(we[r-1]-we[l-1])+ll(r-l)*dep[u]-(get(u,rt[r-1])-get(u,rt[l-1])<<1);
cout<return 0;
}