[BZOJ4876][ZJOI2017]线段树

没有用到任何算法,代码只有60+行,但是细节多如牛毛,各种分类讨论必须全部想清楚才行。

https://www.cnblogs.com/xiejiadong/p/6811289.html

 1 #include<cstdio>
 2 #include<algorithm>
 3 #define rep(i,l,r) for (int i=l; i<=r; i++)
 4 typedef long long ll;
 5 using namespace std;
 6 
 7 const int N=800100;
 8 ll n,nd,tot,m,u,l,r,S,mid[N],ls[N],rs[N],sm[N][2],dep[N],sd[N][2],fa[N][20],L[N],R[N],pos[N];
 9 
10 bool bel(int x,int y){ return L[x]>=L[y] && R[x]<=R[y]; }
11 ll lca(ll a,ll b){
12     if (bel(a,b)) return b;
13     if (bel(b,a)) return a;
14     ll now=a;
15     for (ll i=S; ~i; i--) if (fa[now][i] && !bel(b,fa[now][i])) now=fa[now][i];
16     return fa[now][0];
17 }
18 
19 void Dfs(ll x){
20     if (!ls[x]) return;
21     sm[rs[x]][0]=sm[x][0]; sm[rs[x]][1]=sm[x][1]+1;
22     sm[ls[x]][0]=sm[x][0]+1; sm[ls[x]][1]=sm[x][1];
23     dep[ls[x]]=dep[rs[x]]=dep[x]+1;
24     sd[rs[x]][0]=sd[x][0]; sd[rs[x]][1]=sd[x][1]+dep[x]+1;
25     sd[ls[x]][0]=sd[x][0]+dep[x]+1; sd[ls[x]][1]=sd[x][1];
26     Dfs(ls[x]); Dfs(rs[x]);
27 }
28 
29 ll dfs(ll l,ll r){
30     ll x=++nd; L[x]=l; R[x]=r;
31     for (ll i=0; fa[fa[x][i]][i]; i++) fa[x][i+1]=fa[fa[x][i]][i];
32     if (l==r) return pos[l]=x;
33     ll m=mid[tot++];
34     fa[nd+1][0]=x; ls[x]=dfs(l,m);
35     fa[nd+1][0]=x; rs[x]=dfs(m+1,r);
36     return x;
37 }
38 
39 ll getl(ll l){
40     ll lc=lca(l,u),x=dep[lc]*(sm[l][0]-sm[lc][0])+(bel(l,ls[lc]) && lc!=u)+sd[lc][0]-sm[lc][0];
41     return sd[l][0]+sm[l][0]*dep[u]-x*2;
42 }
43 
44 ll getr(ll r){
45     ll lc=lca(r,u),x=dep[lc]*(sm[r][1]-sm[lc][1])+(bel(r,rs[lc]) && lc!=u)+sd[lc][1]-sm[lc][1];
46     return sd[r][1]+sm[r][1]*dep[u]-x*2;
47 }
48 
49 int main(){
50     freopen("segment.in","r",stdin);
51     freopen("segment.out","w",stdout);
52     scanf("%lld",&n);
53     for (ll i=1; i<=n; i<<=1) S++;
54     for (ll i=1; i<n; i++) scanf("%lld",&mid[i]);
55     tot=1; dfs(1,n); Dfs(1);
56     for (scanf("%lld",&m); m--; ){
57         scanf("%lld%lld%lld",&u,&l,&r); l--; r++;
58         if (!l && r>n) { printf("%lld\n",dep[u]); continue; }
59         ll ans=0;
60         if (l) ans+=getl(pos[l])-((r<=n)?getl(ls[lca(pos[l],pos[r])]):0);
61         if (r<=n) ans+=getr(pos[r])-(l?getr(rs[lca(pos[l],pos[r])]):0);
62         printf("%lld\n",ans);
63     }
64     return 0;
65 }

 

posted @ 2018-03-15 19:00  HocRiser  阅读(366)  评论(0编辑  收藏  举报