膜PoPoQQQ:http://blog.csdn.net/popoqqq/article/details/45365043
省选前学动态树分治
跑起来飞快 45s+
看着提交记录 只能说惨不忍睹 爆int呆滞了一早上 还有因为没删文件 没强制在线 RE的
动态树分治 印象中还有 幻想乡战略游戏和捉迷藏
代码注释一大片 丑我也不管了
#include<cstdio> #include<cstdlib> #include<algorithm> #include<queue> #define V G[p].v using namespace std; typedef long long ll; typedef pair<int,long long> data; typedef vector<data> abcd; pair<ll,int> operator + (const pair<ll,int> x,const pair<ll,int> y) { return make_pair(x.first+y.first,x.second+y.second); } pair<ll,int> operator - (const pair<ll,int> x,const pair<ll,int> y) { return make_pair(x.first-y.first,x.second-y.second); } inline char nc() { static char buf[100000],*p1=buf,*p2=buf; if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; } return *p1++; } inline void read(int &x) { char c=nc(),b=1; for (; !(c>='0' && c<='9'); c=nc()) if (c=='-') b=-1; for (x=0; c>='0' && c<='9'; x=x*10+c-'0',c=nc()); } inline void read(ll &x) { char c=nc(),b=1; for (; !(c>='0' && c<='9'); c=nc()) if (c=='-') b=-1; for (x=0; c>='0' && c<='9'; x=x*10+c-'0',c=nc()); } inline void read(char &x) { for (x=nc(); x!='C' && x!='G'; x=nc()); } namespace ST { int maxn; ll st[300005][20]; int Log[300005]; inline void Pre(int n,ll *a) { maxn=n; for (int i=2; i<=n; i++) Log[i]=Log[i>>1]+1; for (int i=1; i<=n; i++) st[i][0]=a[i]; for (int k=1; k<=19; k++) for (int i=1; i<=n; i++) { st[i][k]=st[i][k-1]; if (i+(1<<(k-1))<=maxn) st[i][k]=min(st[i][k-1],st[i+(1<<(k-1))][k-1]); } } inline ll Query(int l,int r) { if (l>r) swap(l,r); int t=Log[r-l+1]; return min(st[l][t],st[r-(1<<t)+1][t]); } } struct edge { int u,v,next; ll w; }; edge G[300005]; int head[150005],inum; inline void add(int u,int v,ll w,int p) { G[p].u=u; G[p].v=v; G[p].w=w; G[p].next=head[u]; head[u]=p; } int n,tot,A; int a[150005]; ll depth[150005]; int size[150005],del[150005],fat[150005]; ll ia[300005],clk; int pos[150005]; abcd sum1[150005],sum2[150005]; inline void dfs(int u,int fa) { ia[++clk]=depth[u]; pos[u]=clk; for (int p=head[u]; p; p=G[p].next) if (V!=fa) { depth[V]=depth[u]+G[p].w; dfs(V,u),ia[++clk]=depth[u]; } } inline ll dis(int u,int v) { return depth[u]+depth[v]-2*ST::Query(pos[u],pos[v]); } int sum,rt,minimum; inline void Root(int u,int fa) { int maximum=0; size[u]=1; for (int p=head[u]; p; p=G[p].next) if (V!=fa && !del[V]) { Root(V,u); size[u]+=size[V]; maximum=max(maximum,size[V]); } maximum=max(maximum,sum-size[u]); if (minimum>maximum) minimum=maximum,rt=u; } inline void dfs(int u,int fa,ll d,abcd &sum1,abcd &sum2) { size[u]=1; sum1.push_back(data(a[u],d)); sum2.push_back(data(a[u],d)); for (int p=head[u];p;p=G[p].next) if (V!=fa && !del[V]) dfs(V,u,d+G[p].w,sum1,sum2),size[u]+=size[V]; } inline void Divi(int u) { del[u]=1; sum1[u].push_back(data(a[u],0)); for (int p=head[u]; p; p=G[p].next) if (!del[V]) { abcd itmp; dfs(V,u,G[p].w,sum1[u],itmp); sum=size[V]; minimum=1<<30; Root(V,u); int cg=rt; fat[cg]=u; Divi(cg); sum2[cg]=itmp; sum2[cg].push_back(data(-1,0)); sort(sum2[cg].begin(),sum2[cg].end()); for(int j=1;j<sum2[cg].size();j++) sum2[cg][j].second+=sum2[cg][j-1].second; } sum1[u].push_back(data(-1,0)); sort(sum1[u].begin(),sum1[u].end()); for(int j=1;j<sum1[u].size();j++) sum1[u][j].second+=sum1[u][j-1].second; } inline pair<ll,int> Query(abcd &a,int l,int r){ if (a.empty()) return pair<ll,int>(0,0); // for (int j=0;j<a.size();j++) // printf("(%d,%lld)",a[j].first,a[j].second); // printf("\n"); abcd::iterator it1=lower_bound(a.begin(),a.end(),data(l,0)); abcd::iterator it2=lower_bound(a.begin(),a.end(),data(r+1,0)); it1--; it2--; // printf("(%d,%lld)\n",it1->first,it1->second); // printf("(%d,%lld)\n",it2->first,it2->second); // printf("%lld\n",it2->second-it1->second); return make_pair(it2->second-it1->second,it2-it1); } inline ll Query(int x,int l,int r){ ll ret=Query(sum1[x],l,r).first; for (int i=x;fat[i];i=fat[i]){ pair<ll,int> itmp=Query(sum1[fat[i]],l,r)-Query(sum2[i],l,r); ret+=itmp.first+itmp.second*dis(x,fat[i]); } return ret; } int main() { int _u,_v,Q; ll _w,_a,_b; freopen("t.in","r",stdin); freopen("t.out","w",stdout); read(n); read(Q); read(A); for (int i=1; i<=n; i++) read(a[i]); for (int i=1; i<n; i++) read(_u),read(_v),read(_w),add(_u,_v,_w,++inum),add(_v,_u,_w,++inum); dfs(1,0); ST::Pre(clk,ia); minimum=1<<30; sum=n; Root(1,0); Divi(rt); /*for (int i=1;i<=n;i++,putchar('\n')) for (int j=0;j<sum1[i].size();j++) printf("(%d,%lld)",sum1[i][j].first,sum1[i][j].second); for (int i=1;i<=n;i++,putchar('\n')) for (int j=0;j<sum2[i].size();j++) printf("(%d,%lld)",sum2[i][j].first,sum2[i][j].second);*/ ll lastans=0; while (Q--) { read(_u); read(_a); read(_b); (_a+=lastans)%=A; (_b+=lastans)%=A; if (_a>_b) swap(_a,_b); lastans=Query(_u,_a,_b); printf("%lld\n",lastans); } return 0; }