zoukankan      html  css  js  c++  java
  • [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
    ",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
    ",ans);
    63     }
    64     return 0;
    65 }
  • 相关阅读:
    解决硬盘分区无法挂载的问题
    Java EE学习记录(一)
    Netbeans 8.2启动参数含义及配置
    汉化CodeBlock
    linux解决无法打开资源管理器
    netbean下搭建mariadb数据库
    mariadb中执行数据库脚本的方法
    修复受损的linux引导
    修复无法启动的mariadb
    no update
  • 原文地址:https://www.cnblogs.com/HocRiser/p/8575523.html
Copyright © 2011-2022 走看看