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 MBSubmit: 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
0
0
1
1
1 4 3
1 4 2
Sample Output
8
5
5
HINT
共5组数据,n与q的规模分别为10000,20000,30000,40000,50000。