您的位置:首页 > 其它

bzoj4012(动态点分治+卡常数)

2017-02-08 23:06 337 查看
这是一种类型的动态点分治

 

动态点分治,关键还是要在均摊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
,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
,fa
;ll dis
;
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
;
/////////////
int size
,sum,mi,rt;
bool b
;
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;
}


 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: