zoukankan      html  css  js  c++  java
  • BZOJ 3626 [LNOI2014]LCA:树剖 + 差分 + 离线【将深度转化成点权之和】

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3626

    题意:

      给出一个n个节点的有根树(编号为0到n-1,根节点为0,n <= 50000)。

      一个点的深度定义为这个节点到根的距离+1。

      设dep[i]表示点i的深度,LCA(i,j)表示i与j的最近公共祖先。

      有q次询问,每次询问给出l,r,z,求∑ dep[LCA(i,z)] (l<=i<=r)。

      (即,求在[l,r]区间内的每个节点i与z的最近公共祖先的深度之和)

    题解:

      假设有一棵所有点都为0的树。

      如果将x到root路径上的点都+1,则dep[LCA(x,y)] = y到root路径上的点权之和,且这个操作具有叠加性。(树剖)

      所以对于询问query(l to r) = query(r) - query(l-1)。(差分)

      显然,只需要求出在询问中有的l和r的query。

      所以依次枚举节点i = 0 to n-1,将i到root的路径+1,如果i是某一些询问的l或r,则记录相应的query(z)。(离线)

      总复杂度O((n+q)*logn*logn)

    AC Code:

      1 #include <iostream>
      2 #include <stdio.h>
      3 #include <string.h>
      4 #include <vector>
      5 #define MAX_N 200005
      6 #define MAX_M 50005
      7 #define MOD 201314
      8 
      9 using namespace std;
     10 
     11 struct Query
     12 {
     13     int ver;
     14     int id;
     15     int dr;
     16     Query(int _ver,int _id,int _dr)
     17     {
     18         ver=_ver;
     19         id=_id;
     20         dr=_dr;
     21     }
     22     Query(){};
     23 };
     24 
     25 int n,m;
     26 int tot=0;
     27 int cnt=0;
     28 int l[MAX_M];
     29 int r[MAX_M];
     30 int z[MAX_M];
     31 int dat[MAX_N];
     32 int lazy[MAX_N];
     33 int lson[MAX_N];
     34 int rson[MAX_N];
     35 int par[MAX_N];
     36 int dep[MAX_N];
     37 int siz[MAX_N];
     38 int tp[MAX_N];
     39 int son[MAX_N];
     40 int dfsx[MAX_N];
     41 int ans[MAX_M][2];
     42 vector<int> edge[MAX_N];
     43 vector<Query> q[MAX_M];
     44 
     45 inline int mod(int x)
     46 {
     47     return (x%MOD+MOD)%MOD;
     48 }
     49 
     50 int build(int l,int r)
     51 {
     52     int rt=++tot;
     53     dat[rt]=lazy[rt]=0;
     54     lson[rt]=rson[rt]=0;
     55     if(l<r)
     56     {
     57         int mid=(l+r)>>1;
     58         lson[rt]=build(l,mid);
     59         rson[rt]=build(mid+1,r);
     60     }
     61     return rt;
     62 }
     63 
     64 void push_down(int k,int len)
     65 {
     66     if(lazy[k])
     67     {
     68         if(lson[k])
     69         {
     70             dat[lson[k]]=mod(dat[lson[k]]+lazy[k]*(len-(len>>1)));
     71             lazy[lson[k]]=mod(lazy[lson[k]]+lazy[k]);
     72         }
     73         if(rson[k])
     74         {
     75             dat[rson[k]]=mod(dat[rson[k]]+lazy[k]*(len>>1));
     76             lazy[rson[k]]=mod(lazy[rson[k]]+lazy[k]);
     77         }
     78         lazy[k]=0;
     79     }
     80 }
     81 
     82 void push_up(int k)
     83 {
     84     dat[k]=0;
     85     if(lson[k]) dat[k]=mod(dat[k]+dat[lson[k]]);
     86     if(rson[k]) dat[k]=mod(dat[k]+dat[rson[k]]);
     87 }
     88 
     89 void update(int a,int b,int k,int l,int r,int x)
     90 {
     91     if(a<=l && r<=b)
     92     {
     93         dat[k]=mod(dat[k]+(r-l+1)*x);
     94         lazy[k]=mod(lazy[k]+x);
     95         return;
     96     }
     97     if(r<a || b<l) return;
     98     push_down(k,r-l+1);
     99     int mid=(l+r)>>1;
    100     update(a,b,lson[k],l,mid,x);
    101     update(a,b,rson[k],mid+1,r,x);
    102     push_up(k);
    103 }
    104 
    105 int query(int a,int b,int k,int l,int r)
    106 {
    107     if(a<=l && r<=b) return dat[k];
    108     if(r<a || b<l) return 0;
    109     push_down(k,r-l+1);
    110     int mid=(l+r)>>1;
    111     int v1=query(a,b,lson[k],l,mid);
    112     int v2=query(a,b,rson[k],mid+1,r);
    113     return mod(v1+v2);
    114 }
    115 
    116 void dfs1(int now,int d)
    117 {
    118     dep[now]=d;
    119     siz[now]=1;
    120     for(int i=0;i<edge[now].size();i++)
    121     {
    122         int temp=edge[now][i];
    123         if(temp!=par[now])
    124         {
    125             dfs1(temp,d+1);
    126             siz[now]+=siz[temp];
    127         }
    128     }
    129 }
    130 
    131 void dfs2(int now,int anc)
    132 {
    133     tp[now]=anc;
    134     son[now]=-1;
    135     dfsx[now]=++cnt;
    136     for(int i=0;i<edge[now].size();i++)
    137     {
    138         int temp=edge[now][i];
    139         if((son[now]==-1 || siz[temp]>siz[son[now]]) && temp!=par[now])
    140         {
    141             son[now]=temp;
    142         }
    143     }
    144     if(son[now]!=-1) dfs2(son[now],anc);
    145     for(int i=0;i<edge[now].size();i++)
    146     {
    147         int temp=edge[now][i];
    148         if(temp!=par[now] && temp!=son[now]) dfs2(temp,temp);
    149     }
    150 }
    151 
    152 void update_chain(int a,int x)
    153 {
    154     while(tp[a]!=0)
    155     {
    156         update(dfsx[tp[a]],dfsx[a],1,1,n,x);
    157         a=par[tp[a]];
    158     }
    159     update(1,dfsx[a],1,1,n,x);
    160 }
    161 
    162 int query_chain(int a)
    163 {
    164     int sum=0;
    165     while(tp[a]!=0)
    166     {
    167         sum=mod(sum+query(dfsx[tp[a]],dfsx[a],1,1,n));
    168         a=par[tp[a]];
    169     }
    170     sum=mod(sum+query(1,dfsx[a],1,1,n));
    171     return sum;
    172 }
    173 
    174 void read()
    175 {
    176     scanf("%d%d",&n,&m);
    177     for(int i=1;i<n;i++)
    178     {
    179         scanf("%d",&par[i]);
    180         edge[i].push_back(par[i]);
    181         edge[par[i]].push_back(i);
    182     }
    183 }
    184 
    185 void solve()
    186 {
    187     build(1,n);
    188     dfs1(0,0);
    189     dfs2(0,0);
    190     for(int i=0;i<m;i++)
    191     {
    192         scanf("%d%d%d",&l[i],&r[i],&z[i]);
    193         if(l[i]>0) q[l[i]-1].push_back(Query(z[i],i,0));
    194         q[r[i]].push_back(Query(z[i],i,1));
    195     }
    196     memset(ans,0,sizeof(ans));
    197     for(int i=0;i<n;i++)
    198     {
    199         update_chain(i,1);
    200         for(int j=0;j<q[i].size();j++)
    201         {
    202             Query temp=q[i][j];
    203             ans[temp.id][temp.dr]=query_chain(temp.ver);
    204         }
    205     }
    206 }
    207 
    208 void print()
    209 {
    210     for(int i=0;i<m;i++)
    211     {
    212         printf("%d
    ",mod(ans[i][1]-ans[i][0]));
    213     }
    214 }
    215 
    216 int main()
    217 {
    218     read();
    219     solve();
    220     print();
    221 }
  • 相关阅读:
    C函数调用
    C语言的起源
    使用对象流将数据以对象形式进行读写
    使用File类新建一个文本文件
    Windows下架设本机上Subversion服务器
    本地svn版本管理搭建
    ExtJs-第一讲
    找工作经历
    浅谈HashMap的实现原理(转载)
    异常
  • 原文地址:https://www.cnblogs.com/Leohh/p/7955529.html
Copyright © 2011-2022 走看看