您的位置:首页 > 其它

BZOJ 3626 [LNOI2014]LCA

2016-07-13 19:31 309 查看
给出一个n个节点的有根树。有q次询问,求在[l,r]区间内的每个节点i与z的最近公共祖先的深度之和)。

共5组数据,n与q的规模分别为10000,20000,30000,40000,50000。

树链剖分+BIT

PS:用BIT求区间和非常赞

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=50005;

void rd(int &r){
r=0;char c;
while(c=getchar(),c<48);
do r=r*10+(c^48);
while(c=getchar(),c>47);
}

int n,Q;

int last[maxn],ecnt;
struct Edge{
int to,nxt;
}edge[maxn<<1];
void ins(int u,int v){
edge[++ecnt]=(Edge){v,last[u]};
last[u]=ecnt;
}

int frm[maxn];
int head[maxn],qcnt;
struct Query{
int id,w,nxt;
}qury[maxn<<1];
void ins_(int id,int w,int to){
qury[++qcnt]=(Query){id,w,head[to]};
head[to]=qcnt;
}

int dfs_clock;
int segID[maxn];
int sz[maxn];
int link[maxn],par[maxn];

void dfs(int x){
sz[x]=1;
for(int i=last[x];i;i=edge[i].nxt){
int to=edge[i].to;
par[to]=x;
dfs(to);
sz[x]+=sz[to];
}
}
void assign(int x,int f){
segID[x]=++dfs_clock;
link[x]=f;
int mx=0;
for(int i=last[x];i;i=edge[i].nxt){
int to=edge[i].to;
if(sz[to]>sz[mx])
mx=to;
}
if(!mx)return;
assign(mx,f);
for(int i=last[x];i;i=edge[i].nxt){
int to=edge[i].to;
if(mx!=to)
assign(to,to);
}
}

struct SUM{
struct BIT{
int v[maxn];
void update(int x,int f){
for(;x<=n;x+=x&-x)v[x]+=f;
}
int query(int x){
int res=0;
for(;x;x-=x&-x)res+=v[x];
return res;
}
}bit[2];
void update(int l,int r,int x){
bit[0].update(l,(1-l)*x);
bit[0].update(r+1,r*x);
bit[1].update(l,x);
bit[1].update(r+1,-x);
}
int query(int l,int r){
int rsum=bit[1].query(r)*r+bit[0].query(r);
int lsum=bit[1].query(l-1)*(l-1)+bit[0].query(l-1);
return rsum-lsum;
}
}sum;

void update(int x){
while(link[x]!=0){
sum.update(segID[link[x]],segID[x],1);
x=par[link[x]];
}
}

int Ans[maxn];

void query(int y){
int id=qury[y].id;
int x=frm[id];
int w=qury[y].w;
while(link[x]!=0){
Ans[id]+=w*sum.query(segID[link[x]],segID[x]);
x=par[link[x]];
}
}

void solve(){
dfs(1);
assign(1,1);
for(int i=1;i<=n;i++){
update(i);
for(int j=head[i];j;j=qury[j].nxt)
query(j);
}
}

void input(){
rd(n);rd(Q);
for(int u,i=2;i<=n;i++){
rd(u);++u;
ins(u,i);
}
for(int l,r,i=1;i<=Q;i++){
rd(l);rd(r);rd(frm[i]);
++l;++r;++frm[i];
ins_(i,1,r);
if(l!=1)ins_(i,-1,l-1);
}
}

const int mod=201314;

void output(){
for(int i=1;i<=Q;i++)
printf("%d\n",Ans[i]%mod);
}
int main(){

input();
solve();
output();

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