zoukankan      html  css  js  c++  java
  • 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的父节点编号。
    接下来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

    解题思路:

    蒟蒻QAQ的我一开始以为是树上莫队。

    还好吧,这题其实是将Deep重新理解了一下,就是从根到这个点的距离。

    我们发现可以在树链上(到1)加一,最后查询到根的权值和。

    发现具有区间可减性。

    线段树+树剖搞定。

    代码:

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #define lll spc<<1
      5 #define rrr spc<<1|1
      6 typedef long long lnt;
      7 const lnt mod=201314;
      8 using std::sort;
      9 struct trnt{
     10     lnt lzt;
     11     lnt val;
     12 }tr[1000000];
     13 struct pnt{
     14     int hd;
     15     int fa;
     16     int tp;
     17     int dp;
     18     int no;
     19     int wgt;
     20     int ind;
     21     int mxs;
     22 }p[1000000];
     23 struct ent{
     24     int twd;
     25     int lst;
     26 }e[1000000];
     27 int ans[1000000];
     28 struct data{
     29     int no;
     30     bool lft;
     31     int rgt;
     32     int z;
     33 }dt[1000000];
     34 int cnt;
     35 int dfn;
     36 int n,q;
     37 bool cmp(data x,data y)
     38 {
     39     return x.rgt<y.rgt;
     40 }
     41 void ade(int f,int t)
     42 {
     43     cnt++;
     44     e[cnt].twd=t;
     45     e[cnt].lst=p[f].hd;
     46     p[f].hd=cnt;
     47     return ;
     48 }
     49 void add(int l,int r,int spc,lnt x)
     50 {
     51     if(!spc)
     52         return ;
     53     tr[spc].lzt=(tr[spc].lzt+x)%mod;
     54     tr[spc].val=(tr[spc].val+(((lnt)(r-l+1))*x)%mod)%mod;
     55     return ;
     56 }
     57 void pushdown(int spc,int l,int r)
     58 {
     59     if(tr[spc].lzt)
     60     {
     61         int mid=(l+r)>>1;
     62         add(l,mid,lll,tr[spc].lzt);
     63         add(mid+1,r,rrr,tr[spc].lzt);
     64         tr[spc].lzt=0;
     65     }
     66     return ;
     67 }
     68 void pushup(int spc)
     69 {
     70     tr[spc].val=(tr[lll].val+tr[rrr].val)%mod;
     71 }
     72 void update(int l,int r,int ll,int rr,int spc,lnt v)
     73 {
     74     if(ll>r||l>rr)
     75         return ;
     76     if(ll<=l&&r<=rr)
     77     {
     78         add(l,r,spc,v);
     79         return ;
     80     }
     81     pushdown(spc,l,r);
     82     int mid=(l+r)>>1;
     83     update(l,mid,ll,rr,lll,v);
     84     update(mid+1,r,ll,rr,rrr,v);
     85     pushup(spc);
     86     return ;
     87 }
     88 lnt query(int l,int r,int ll,int rr,int spc)
     89 {
     90     if(ll>r||l>rr)
     91         return 0ll;
     92     if(ll<=l&&r<=rr)
     93         return tr[spc].val;
     94     int mid=(l+r)>>1;
     95     pushdown(spc,l,r);
     96     return (query(l,mid,ll,rr,lll)+query(mid+1,r,ll,rr,rrr))%mod;
     97 }
     98 void Basic_dfs(int x,int f)
     99 {
    100     p[x].fa=f;
    101     p[x].dp=p[f].dp+1;
    102     p[x].wgt=1;
    103     int maxs=-1;
    104     for(int i=p[x].hd;i;i=e[i].lst)
    105     {
    106         int to=e[i].twd;
    107         if(to==f)
    108             continue;
    109         Basic_dfs(to,x);
    110         p[x].wgt+=p[to].wgt;
    111         if(p[to].wgt>maxs)
    112         {
    113             maxs=p[to].wgt;
    114             p[x].mxs=to;
    115         }
    116     }
    117 }
    118 void Build_dfs(int x,int top)
    119 {
    120     if(!x)
    121         return ;
    122     p[x].ind=++dfn;
    123     p[x].tp=top;
    124     Build_dfs(p[x].mxs,top);
    125     for(int i=p[x].hd;i;i=e[i].lst)
    126     {
    127         int to=e[i].twd;
    128         if(p[to].ind)
    129             continue;
    130         Build_dfs(to,to);
    131     }
    132     return ;
    133 }
    134 void Insert(int x)
    135 {
    136     while(p[x].tp!=1)
    137     {
    138         update(1,n,p[p[x].tp].ind,p[x].ind,1,1);
    139         x=p[p[x].tp].fa;
    140     }
    141     update(1,n,1,p[x].ind,1,1);
    142     return ;
    143 }
    144 lnt Val(int x)
    145 {
    146     lnt ansl=0;
    147     while(p[x].tp!=1)
    148     {
    149         ansl+=query(1,n,p[p[x].tp].ind,p[x].ind,1);
    150         ansl%=mod;
    151         x=p[p[x].tp].fa;
    152     }
    153     ansl+=query(1,n,1,p[x].ind,1);
    154     ansl%=mod;
    155     return ansl;
    156 }
    157 int main()
    158 {
    159     scanf("%d%d",&n,&q);
    160     for(int i=2;i<=n;i++)
    161     {
    162         int a;
    163         scanf("%d",&a);
    164         a++;
    165         ade(a,i);
    166         ade(i,a);
    167     }
    168     cnt=0;
    169     for(int i=1;i<=q;i++)
    170     {
    171         int tmp;
    172         cnt++;
    173         dt[cnt].no=i;
    174         dt[cnt].lft=true;
    175         scanf("%d",&dt[cnt].rgt);
    176         cnt++;
    177         dt[cnt].no=i;
    178         dt[cnt].lft=false;
    179         scanf("%d",&dt[cnt].rgt);
    180         dt[cnt].rgt++;
    181         scanf("%d",&tmp);
    182         tmp++;
    183         dt[cnt].z=dt[cnt-1].z=tmp;
    184     }
    185     sort(dt+1,dt+cnt+1,cmp);
    186     Basic_dfs(1,1);
    187     Build_dfs(1,1);
    188     int plc=1;
    189     for(int i=1;i<=cnt;i++)
    190     {
    191         while(plc<=dt[i].rgt)
    192         {
    193             Insert(plc);
    194             plc++;
    195         }
    196         int x=dt[i].no;
    197         int pl=dt[i].z;
    198         lnt tmp=Val(pl);
    199         if(dt[i].lft)
    200             tmp=-tmp;
    201         ans[x]=(ans[x]+tmp)%mod;
    202     }
    203     for(int i=1;i<=q;i++)
    204         printf("%lld
    ",(ans[i]%mod+mod)%mod);
    205     return 0;
    206 }
  • 相关阅读:
    安卓开发_浅谈TimePicker(时间选择器)
    eclipse显示代码行数
    Java数据解析---JSON
    Java数据解析---PULL
    Java数据解析---SAX
    统计机器学习(目录)
    FP Tree算法原理总结
    梯度下降(Gradient Descent)小结
    用scikit-learn和pandas学习线性回归
    用scikit-learn学习BIRCH聚类
  • 原文地址:https://www.cnblogs.com/blog-Dr-J/p/9713257.html
Copyright © 2011-2022 走看看