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\n",(ans[i]%mod+mod)%mod);
205     return 0;
206 }

 

posted @ 2018-09-27 15:18  Unstoppable728  阅读(161)  评论(0编辑  收藏  举报