# bzoj 4012: [HNOI2015]开店

Description

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#define RG register
#define il inline
#define iter iterator
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;
typedef long long ll;
const int N=150005;
int bt=0,b[N],a[N];ll sum[N],w[N],sed[N];
int gi(){
int str=0;char ch=getchar();
while(ch>'9' || ch<'0')ch=getchar();
while(ch>='0' && ch<='9')str=(str<<1)+(str<<3)+ch-48,ch=getchar();
return str;
}
bool comp(int i,int j){return edg[i]<edg[j];}
int ids=0,fa[N],top[N],id[N],son[N],sz[N];ll path[N];
void dfs1(int x){
int u;
sz[x]=1;
u=to[i];if(sz[u])continue;
path[u]=path[x]+dis[i];fa[u]=x;
val[u]=dis[i];dfs1(u);sz[x]+=sz[u];
if(sz[u]>sz[son[x]])son[x]=u;
}
}
void dfs2(int x,int tp){
id[x]=++ids;top[x]=tp;
if(son[x])dfs2(son[x],tp);int u;
u=to[i];if(u==fa[x] || u==son[x])continue;
dfs2(u,u);
}
}
int root[N],totnode=0;
struct node{
int lazy,l,r;ll sum;
}tr[N*30];
void upd(int rt,int l,int r){
tr[rt].sum=tr[tr[rt].l].sum+tr[tr[rt].r].sum+tr[rt].lazy*(w[r]-w[l-1]);
}
void updata(int &rt,int last,int l,int r,int sa,int se){
rt=++totnode;tr[rt]=tr[last];
if(sa==l && r==se){
tr[rt].sum+=w[r]-w[l-1];
tr[rt].lazy++;
return ;
}
int mid=(l+r)>>1;
if(se<=mid)updata(tr[rt].l,tr[last].l,l,mid,sa,se);
else if(sa>mid)updata(tr[rt].r,tr[last].r,mid+1,r,sa,se);
else{
updata(tr[rt].l,tr[last].l,l,mid,sa,mid);
updata(tr[rt].r,tr[last].r,mid+1,r,mid+1,se);
}
upd(rt,l,r);
}
void updpath(int x){
int rt=edg[x];
while(x){
updata(root[rt],root[rt],1,n,id[top[x]],id[x]);
x=fa[top[x]];
}
}
void solve(){
sort(a+1,a+n+1,comp);
dfs1(1);dfs2(1,1);
for(int i=1;i<=n;i++)w[id[i]]=val[i],sed[edg[i]]+=path[i];
for(int i=1;i<=n;i++)w[i]+=w[i-1],sed[i]+=sed[i-1];
for(int j=1,i;j<=n;j++){
i=a[j];
if(!root[edg[i]])
root[edg[i]]=root[edg[i]-1];
updpath(i);
}
}
ll query(int rt,int l,int r,int sa,int se,int mr){
if(l==sa && r==se)return tr[rt].sum+(ll)mr*(w[r]-w[l-1]);
int mid=(l+r)>>1;ll ret=0;mr+=tr[rt].lazy;
if(se<=mid)ret=query(tr[rt].l,l,mid,sa,se,mr);
else if(sa>mid)ret=query(tr[rt].r,mid+1,r,sa,se,mr);
else{
ret+=query(tr[rt].l,l,mid,sa,mid,mr);
ret+=query(tr[rt].r,mid+1,r,mid+1,se,mr);
}
return ret;
}
ll qtree(int x,int fr){
if(fr==0)return 0;
ll ret=0;int rt=root[fr];
while(x){
ret+=query(rt,1,n,id[top[x]],id[x],0);
x=fa[top[x]];
}
return ret;
}
void settle(){
ll ret=0,ans=0,u,x,y,xa,xb;
while(Q--){
u=gi();xa=gi();xb=gi();
x=Min((xa+ans)%A,(xb+ans)%A);
y=Max((xa+ans)%A,(xb+ans)%A);
x=lower_bound(b+1,b+tot+1,x)-b;
y=upper_bound(b+1,b+tot+1,y)-b-1;
ret=(ll)(sum[y]-sum[x-1])*path[u];
ret+=sed[y]-sed[x-1];
ret-=(ll)(qtree(u,y)-qtree(u,x-1))<<1;
ans=ret;
printf("%lld\n",ans);
}
}
void work()
{
n=gi();Q=gi();A=gi();
for(int i=1;i<=n;i++)edg[i]=gi(),b[++bt]=edg[i],a[i]=i;
int x,y,z;
for(int i=1;i<n;i++){
x=gi();y=gi();z=gi();
}
sort(b+1,b+bt+1);
tot=unique(b+1,b+bt+1)-b-1;
for(int i=1;i<=n;i++)edg[i]=lower_bound(b+1,b+tot+1,edg[i])-b;
for(int i=1;i<=n;i++)sum[edg[i]]++;
for(int i=1;i<=tot;i++)sum[i]+=sum[i-1];
solve();settle();
}

int main()
{
work();
return 0;
}


posted @ 2017-09-11 17:03  PIPIBoss  阅读(123)  评论(2编辑  收藏  举报