bzoj4012(動態點分治+卡常數)

這是一種類型的動態點分治

 

動態點分治,關鍵還是要在均攤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;
}


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章