zoukankan      html  css  js  c++  java
  • bzoj 3626 LCA

    题目大意:

    给出一个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的最近公共祖先的深度之和)

    思路:

    lca可以用类似于差分的思路来维护:

    若求x和y的LCA的深度 可以把x到根上的路径上的每个点的权值+1 

    然后求y到根上所有点的权值和就行了,这样恰好能表示LCA的深度

    这样我们就可以把所有l和r离线下来排序

    然后按照1 - n 的顺序logn修改每个点到根的路径上的点权

    然后查询

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cmath>
      4 #include<cstdlib>
      5 #include<cstring>
      6 #include<algorithm>
      7 #include<vector>
      8 #include<queue>
      9 #define inf 2139062143
     10 #define ll long long
     11 #define MAXN 50101
     12 #define MOD 201314
     13 using namespace std;
     14 inline int read()
     15 {
     16     int x=0,f=1;char ch=getchar();
     17     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
     18     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
     19     return x*f;
     20 }
     21 int n,z[MAXN],ans[MAXN];
     22 int Cnt,cnt[MAXN],bl[MAXN],fa[MAXN],hsh[MAXN];
     23 int fst[MAXN],nxt[MAXN<<1],to[MAXN<<1];
     24 struct data {int l,r,sum,tag;}tr[MAXN<<2];
     25 struct Qst {int num,pos;bool f;}g[MAXN<<1];
     26 bool cmp(Qst a,Qst b) {return a.pos<b.pos;}
     27 void add(int u,int v) {nxt[++Cnt]=fst[u],fst[u]=Cnt,to[Cnt]=v;}
     28 void dfs(int x)
     29 {
     30     cnt[x]=1;
     31     for(int i=fst[x];i;i=nxt[i])
     32     {
     33         if(to[i]==fa[x]) continue;
     34         dfs(to[i]);
     35         cnt[x]+=cnt[to[i]];
     36     }
     37 }
     38 void Dfs(int x,int anc)
     39 {
     40     bl[x]=anc,hsh[x]=++Cnt;
     41     int hvs=0;
     42     for(int i=fst[x];i;i=nxt[i])
     43         if(to[i]!=fa[x]&&cnt[to[i]]>cnt[hvs]) hvs=to[i];
     44     if(!hvs) return ;
     45     Dfs(hvs,anc);
     46     for(int i=fst[x];i;i=nxt[i])
     47         if(to[i]!=fa[x]&&to[i]!=hvs) Dfs(to[i],to[i]);
     48 }
     49 void build(int k,int l,int r)
     50 {
     51     tr[k].l=l,tr[k].r=r,tr[k].sum=tr[k].tag=0;
     52     if(l==r) return ;
     53     int mid=(l+r)>>1;
     54     build(k<<1,l,mid);
     55     build(k<<1|1,mid+1,r);
     56 }
     57 void pshd(int k)
     58 {
     59     tr[k<<1].tag=tr[k].tag+tr[k<<1].tag;tr[k<<1|1].tag+=tr[k].tag;
     60     tr[k<<1].sum+=(tr[k<<1].r-tr[k<<1].l+1)*tr[k].tag,tr[k<<1|1].sum+=(tr[k<<1|1].r-tr[k<<1|1].l+1)*tr[k].tag;
     61     tr[k].tag=0;
     62 }
     63 void upd(int k,int a,int b)
     64 {
     65     int l=tr[k].l,r=tr[k].r;
     66     if(a==l&&b==r) {tr[k].sum+=r-l+1,tr[k].tag++;return ;}
     67     if(tr[k].tag) pshd(k);
     68     int mid=(l+r)>>1;
     69     if(mid>=b) upd(k<<1,a,b);
     70     else if(mid<a) upd(k<<1|1,a,b);
     71     else {upd(k<<1,a,mid);upd(k<<1|1,mid+1,b);}
     72     tr[k].sum=tr[k<<1].sum+tr[k<<1|1].sum;
     73 }
     74 int query(int k,int a,int b)
     75 {
     76     int l=tr[k].l,r=tr[k].r;
     77     if(a==l&&b==r) return tr[k].sum%MOD;
     78     int mid=(l+r)>>1;
     79     if(tr[k].tag) pshd(k);
     80     if(mid>=b) return query(k<<1,a,b)%MOD;
     81     else if(mid<a) return query(k<<1|1,a,b)%MOD;
     82     else return (query(k<<1,a,mid)+query(k<<1|1,mid+1,b))%MOD;
     83 }
     84 void Fill(int x)
     85 {
     86     while(bl[x]!=1)
     87     {
     88         upd(1,hsh[bl[x]],hsh[x]);
     89         x=fa[bl[x]];
     90     }
     91     upd(1,1,hsh[x]);
     92 }
     93 int Query(int x)
     94 {
     95     int res=0;
     96     while(bl[x]!=1)
     97     {
     98         (res+=query(1,hsh[bl[x]],hsh[x]))%=MOD;
     99         x=fa[bl[x]];
    100     }
    101     (res+=query(1,1,hsh[x]))%=MOD;
    102     return res;
    103 }
    104 int main()
    105 {
    106     n=read();int l,r,t,now=1,T=read();
    107     for(int i=2;i<=n;i++) {fa[i]=read()+1;add(i,fa[i]);add(fa[i],i);}
    108     fa[1]=1,Cnt=0;
    109     dfs(1);Dfs(1,1);build(1,1,n);
    110     for(int i=1;i<=T;i++) 
    111     {
    112         l=read(),r=read()+1,z[i]=read()+1;
    113         g[2*i].num=g[2*i-1].num=i;
    114         g[2*i-1].pos=l,g[2*i].pos=r;
    115         g[2*i-1].f=0,g[2*i].f=1;
    116     }
    117     sort(g+1,g+2*T+1,cmp);
    118     for(int i=1;i<=2*T;i++)
    119     {
    120         if(!g[i].pos) continue;
    121         while(now<=g[i].pos)
    122         {
    123             Fill(now);
    124             now++;
    125         }
    126         if(!g[i].f) ans[g[i].num]=0-Query(z[g[i].num]);
    127         else ans[g[i].num]+=Query(z[g[i].num]);
    128     }
    129     for(int i=1;i<=T;i++) printf("%d
    ",(ans[i]+MOD)%MOD);
    130 }
    View Code

    又一次因为bool导致了1+1=1 

  • 相关阅读:
    杭州办理招行香港一卡通(两地一卡通)攻略
    Android高手进阶教程(二十)之Android与JavaScript方法相互调用!
    Android应用的自动升级、更新模块的实现
    18个最好的jQuery表格插件
    系统的本地策略不允许你采用交互式登录
    android中判断横屏或者竖屏并改变背景
    记录几个东东
    jsAnim学习
    win7下安装oracle10g出现未知错误,程序异常终止
    oracle创建用户并授权
  • 原文地址:https://www.cnblogs.com/yyc-jack-0920/p/8351703.html
Copyright © 2011-2022 走看看