bzoj3626

链剖。。。题解看hz的。。。。离线搞

  1 #include<bits/stdc++.h>
  2 #define lowbit(a) ((a)&(-(a)))
  3 #define l(a) ((a)<<1)
  4 #define r(a) ((a)<<1|1)
  5 #define clr(a,x) memset(a,x,sizeof(a))
  6 #define rep(i,l,r) for(int i=l;i<(r);i++)
  7 #define Rep(i,a) rep(i,0,e[a].size())
  8 typedef long long ll;
  9 using namespace std;
 10 int read()
 11 {
 12     char c=getchar();
 13     int ans=0,f=1;
 14     while(!isdigit(c)){
 15         if(c==‘-‘) f=-1;
 16         c=getchar();
 17     }
 18     while(isdigit(c)){
 19         ans=ans*10+c-‘0‘;
 20         c=getchar();
 21     }
 22     return ans*f;
 23 }
 24 struct node{
 25     int l,r,sum,add;
 26 };
 27 struct query{
 28     int x,p;
 29     bool f;
 30     inline bool operator<(const query&A)const{
 31         return x<A.x;
 32     }
 33 };
 34 const int maxn=50009,mod=201314;
 35 int ans[maxn],n,m,dfstime=0,Top,g[maxn],size[maxn],f[maxn],son[maxn],top[maxn],dep[maxn],id[maxn];
 36 query q[maxn<<1];
 37 node x[maxn<<2];
 38 vector<int>e[maxn];
 39 void dfs(int k){
 40     size[k]=1;
 41     Rep(i,k){
 42         int to=e[k][i];
 43         if(to==f[k]) continue;
 44         f[to]=k;
 45         dep[to]=dep[k]+1;
 46         dfs(to);
 47         size[k]+=size[to];
 48         if(!son[k]||size[son[k]]<size[to]) son[k]=to;
 49     }
 50 }
 51 void Dfs(int k){
 52     top[k]=Top;
 53     id[k]=++dfstime;
 54     if(son[k]) Dfs(son[k]);
 55     Rep(i,k){
 56         int to=e[k][i];
 57         if(!id[to]) Dfs(Top=to);
 58     }
 59 }
 60 void maintain(int k){
 61     x[k].sum=x[l(k)].sum+x[r(k)].sum;
 62 }
 63 void pushdown(int k){
 64     if(x[k].l!=x[k].r&&x[k].add){
 65         x[l(k)].sum+=(x[l(k)].r-x[l(k)].l+1)*x[k].add;
 66         x[r(k)].sum+=(x[r(k)].r-x[r(k)].l+1)*x[k].add;
 67         x[l(k)].add+=x[k].add;
 68         x[r(k)].add+=x[k].add;
 69     }
 70     x[k].add=0;
 71 }
 72 void build(int k,int l,int r){
 73     x[k].l=l,x[k].r=r,x[k].sum=x[k].add=0;
 74     if(l==r) return;
 75     int mid=(l+r)>>1;
 76     build(l(k),l,mid);
 77     build(r(k),mid+1,r);
 78     maintain(k);
 79 }
 80 void modify(int k,int l,int r,int t){
 81     pushdown(k);
 82     if(x[k].l==l&&x[k].r==r){
 83         x[k].sum+=(r-l+1)*t;
 84         x[k].add+=t;
 85         return;
 86     }
 87     int mid=(x[k].l+x[k].r)>>1;
 88     if(r<=mid) modify(l(k),l,r,t);
 89     else if(l>mid) modify(r(k),l,r,t);
 90     else{
 91         modify(l(k),l,mid,t);
 92         modify(r(k),mid+1,r,t);
 93     }
 94     maintain(k);
 95 }
 96 int find(int k,int l,int r){
 97     pushdown(k);
 98     if(x[k].l==l&&x[k].r==r) return x[k].sum;
 99     int mid=(x[k].l+x[k].r)>>1;
100     if(r<=mid) return find(l(k),l,r);
101     if(l>mid) return find(r(k),l,r);
102     return (find(l(k),l,mid)+find(r(k),mid+1,r));
103 }
104 void add(int u,int v,int t){
105     while(top[u]!=top[v]){
106         if(dep[top[u]]<dep[top[v]]) swap(u,v);
107         modify(1,id[top[u]],id[u],t);
108         u=f[top[u]];
109     }
110     if(dep[u]>dep[v]) swap(u,v);
111     modify(1,id[u],id[v],t);
112 }
113 int sum(int u,int v){
114     int ans=0;
115     while(top[u]!=top[v]){
116         if(dep[top[u]]<dep[top[v]]) swap(u,v);
117         ans+=find(1,id[top[u]],id[u]);
118         u=f[top[u]];
119     }
120     if(dep[u]>dep[v]) swap(u,v);
121     ans+=find(1,id[u],id[v]);
122     return ans%mod;
123 }
124 void init(){
125     dep[0]=1;
126     dfs(0);
127     Dfs(Top=0);
128     build(1,1,n);
129 }
130 int main()
131 {
132     n=read(),m=read();
133     rep(i,1,n){
134         int to=read();
135         e[to].push_back(i);
136         e[i].push_back(to);
137     }
138     init();
139     int cnt=0;
140     rep(i,0,m){
141         int l=read(),r=read();g[i]=read();
142         q[cnt].x=l-1;q[cnt].p=i;q[cnt++].f=0;
143         q[cnt].x=r;q[cnt].p=i;q[cnt++].f=1;
144     }
145     m<<=1;
146     sort(q,q+m);
147     cnt=-1;
148     rep(i,0,m){
149         while(cnt<q[i].x){
150             cnt++;
151             add(cnt,0,1);
152         }
153         int t=sum(g[q[i].p],0);
154         ans[q[i].p]=ans[q[i].p]+t*(q[i].f?1:-1);
155     }
156     rep(i,0,m>>1) printf("%d\n",(ans[i]+mod)%mod);
157     return 0;
158 }

3626: [LNOI2014]LCA

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 947  Solved: 325
[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

Sample Output

8
5

HINT

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

Source

数据已加强 by saffah

[Submit][Status][Discuss]

时间: 2024-12-22 05:27:46

bzoj3626的相关文章

bzoj3626 [ LNOI2014 ] -- 树链剖分

直接复制gconeice的题解吧 显然,暴力求解的复杂度是无法承受的.考虑这样的一种暴力,我们把 z 到根上的点全部打标记,对于 l 到 r 之间的点,向上搜索到第一个有标记的点求出它的深度统计答案.观察到,深度其实就是上面有几个已标记了的点(包括自身).所以,我们不妨把 z 到根的路径上的点全部 +1,对于 l 到 r 之间的点询问他们到根路径上的点权和.仔细观察上面的暴力不难发现,实际上这个操作具有叠加性,且可逆.也就是说我们可以对于 l 到 r 之间的点 i,将 i 到根的路径上的点全部

【BZOJ3626】[LNOI2014]LCA 离线+树链剖分+线段树

[BZOJ3626][LNOI2014]LCA 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的父节点编号.接

Bzoj3626 [LNOI2014]LCA

Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 2007  Solved: 800 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的最近公共祖先的深度之和) I

bzoj3626: [LNOI2014]LCA 离线+树链剖分

理解了半天. 题解:http://hzwer.com/3891.html #include<bits/stdc++.h> #define N 50010 #define M (l+r>>1) #define P (k<<1) #define S (k<<1|1) #define K l,r,k #define L l,M,P #define R M+1,r,S #define Z int l=1,int r=n,int k=1 using namespace

bzoj3626【LNOI2014】LCA

3626: [LNOI2014]LCA Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 1266  Solved: 448 [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}de

【BZOJ3626】【LNOI2014】LCA (树剖+离线)

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的最近公共祖先的深度之和)答案对201314取模. 这个题是大饺子安利给我的,然后顺带学了一发树剖(好弱啊). 这个题解讲的很好啦w:http://www.cnbl

【树链剖分】【线段树】bzoj3626 [LNOI2014]LCA

引用题解: http://blog.csdn.net/popoqqq/article/details/38823457 题目大意: 给出一个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的最近公共祖先的深度之和) 这题看见了直接卡壳...然后

BZOJ3626 LNOI2014 LCA 树链剖分

题意:给定一棵树,每次询问给出l r z,求在[l,r]区间内的每个节点i与z的最近公共祖先的深度之和 题解: 显然,暴力求解的复杂度是无法承受的. 考虑这样的一种暴力,我们把 z 到根上的点全部打标记,对于 l 到 r 之间的点,向上搜索到第一个有标记的点求出它的深度统计答案.观察到,深度其实就是上面有几个已标记了的点(包括自身).所以,我们不妨把 z 到根的路径上的点全部 +1,对于 l 到 r 之间的点询问他们到根路径上的点权和.仔细观察上面的暴力不难发现,实际上这个操作具有叠加性,且可逆

bzoj3626: [LNOI2014]LCA (树链剖分)

很神奇的方法 感觉是有生之年都想不到正解的这种 考虑对i 到根的节点权值 + 1,则从根到z的路径和就是lca(i,z)的深度 所以依次把0 ~ n - 1的点权值 + 1 对于询问[l, r] 这个区间关于z 的深度和,就用(1, r) - (1, l - 1)的值表示 详见黄学长的博客啦 http://hzwer.com/3415.html 下面给出代码 #include <cstdio> #include <vector> #include <algorithm>