bzoj3626: [LNOI2014]LCA
膜网上题解。。。♂啊。然后看懂后写的很快。。。从早上调到中午。。。晚上回来继续。。。后重新打了一遍。。。似乎是因为ans在+的时候没有%mod的原因?应该是吧。便A了。。累垮。。。顽强的调试精神可嘉可贺啊~~~
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define rep(i,n) for(int i=1;i<=n;i++) #define clr(x,c) memset(x,c,sizeof(x)) #define REP(i,s,t) for(int i=s;i<=t;i++) #define adde(u,v) add(u,v),add(v,u) #define qwq(x) for(edge *o=head[x];o;o=o->next) #define op() clr(head,0);pt=edges; #define lson l,m,x<<1 #define rson m+1,r,x<<1|1 const int nmax=50005; const int inf=0x7f7f7f7f; const int mod=201314; int read(){ int x=0;char c=getchar();; while(!isdigit(c)){ c=getchar(); } while(isdigit(c)) x=x*10+c-'0',c=getchar(); return x; } struct edge{ int to;edge *next; }; edge edges[nmax<<2],*pt,*head[nmax]; int son[nmax],size[nmax],fa[nmax],dep[nmax],id[nmax],idx[nmax],tp[nmax],col[nmax<<2],sum[nmax<<2],n; void add(int u,int v){ pt->to=v;pt->next=head[u];head[u]=pt++; } void dfs(int x){ size[x]=1; qwq(x) if(o->to!=fa[x]){ int to=o->to; dep[to]=dep[x]+1;fa[to]=x; dfs(to);size[x]+=size[to]; if(!son[x]||size[to]>size[son[x]]) son[x]=to; } } void DFS(int x,int top){ id[++id[0]]=x;idx[x]=id[0];tp[x]=top; if(son[x]) DFS(son[x],top); qwq(x) if(!idx[o->to]) DFS(o->to,o->to); } void pushdown(int x,int cnt){ if(col[x]){ col[x<<1]+=col[x];col[x<<1|1]+=col[x]; sum[x<<1]+=col[x]*(cnt-(cnt>>1));sum[x<<1|1]+=col[x]*(cnt>>1); col[x]=0; } } void update(int tl,int tr,int l,int r,int x){ if(tl<=l&&tr>=r){ col[x]+=1;sum[x]+=r-l+1;return ; } int m=(l+r)>>1;pushdown(x,r-l+1); if(tl<=m) update(tl,tr,lson); if(tr>m) update(tl,tr,rson); sum[x]=sum[x<<1]+sum[x<<1|1]; } void Update(int b){ while(tp[b]!=1) { update(idx[tp[b]],idx[b],1,n,1);b=fa[tp[b]]; } update(1,idx[b],1,n,1); } int query(int tl,int tr,int l,int r,int x){ if(tl<=l&&tr>=r) return sum[x]; int m=(l+r)>>1,ans=0;pushdown(x,r-l+1); if(tl<=m) ans+=query(tl,tr,lson),ans%=mod; if(tr>m) ans+=query(tl,tr,rson),ans%=mod; return ans; } int qsum(int b){ int ans=0; while(tp[b]!=1){ ans+=query(idx[tp[b]],idx[b],1,n,1);ans%=mod;b=fa[tp[b]]; } ans+=query(1,idx[b],1,n,1); return ans%mod; } struct node{ int num,to;bool f; bool operator<(const node&rhs) const{ return to<rhs.to;} }; node nodes[nmax<<1]; int q[nmax][3]; int main(){ op();clr(col,0);clr(sum,0); n=read();int m=read(),u; REP(i,2,n) u=read(),u++,adde(u,i); clr(son,0);clr(idx,0);id[0]=0;dep[1]=0; dfs(1);DFS(1,1); int cur=0,tmp; rep(i,m){ tmp=read(),nodes[++cur].to=tmp,nodes[cur].num=i,nodes[cur].f=true; tmp=read(),tmp++,nodes[++cur].to=tmp,nodes[cur].num=i,nodes[cur].f=false; tmp=read(),tmp++,q[i][0]=tmp; } sort(nodes+1,nodes+m+m+1); cur=1; rep(i,m+m){ while(cur<=nodes[i].to){ Update(cur),cur++; //rep(j,20) printf("%d ",sum[j]);printf("\n"); } if(nodes[i].f) q[nodes[i].num][1]=qsum(q[nodes[i].num][0]); else q[nodes[i].num][2]=qsum(q[nodes[i].num][0]); } rep(i,m) printf("%d\n",(q[i][2]-q[i][1]+mod)%mod); return 0; }
3626: [LNOI2014]LCA
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1753 Solved: 668
[Submit][Status][Discuss]
Description
给出一个n个节点的有根树(编号为0到n-1,根节点为0)。一个点的深度定义为这个节点到根的距离+1。
设dep[i]表示点i的深度,LCA(i,j)表示i与j的最近公共祖先。
有q次询问,每次询问给出l r z,求sigma_{l<=i<=r}dep[LCA(i,z)]。
(即,求在[l,r]区间内的每个节点i与z的最近公共祖先的深度之和)
Input
第一行2个整数n q。
接下来n-1行,分别表示点1到点n-1的父节点编号。
接下来q行,每行3个整数l r z。
Output
输出q行,每行表示一个询问的答案。每个答案对201314取模输出
Sample Input
5 2
0
0
1
1
1 4 3
1 4 2
0
0
1
1
1 4 3
1 4 2
Sample Output
8
5
5
HINT
共5组数据,n与q的规模分别为10000,20000,30000,40000,50000。