bzoj1146整体二分+树链剖分+树状数组

其实也没啥好说的

用树状数组可以O(logn)的查询

套一层整体二分就可以做到O(nlngn)

最后用树链剖分让序列上树

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<iostream>
  4 #include<algorithm>
  5 using namespace std;
  6 inline int read()
  7 {
  8     int x=0,f=1,ch=getchar();
  9     while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘){f=-1;}ch=getchar();}
 10     while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
 11     return x*f;
 12 }
 13 int n,q;
 14 int data[80005];
 15 inline void add(int x,int i)
 16 {
 17     while(x<=n)
 18     {
 19         data[x]+=i;
 20         x+=x&(-x);
 21     }
 22 }
 23 inline int query(int x)
 24 {
 25     int res=0;
 26     while(x>=1)
 27     {
 28         res+=data[x];
 29         x-=x&(-x);
 30     }
 31     return res;
 32 }
 33 int h[80005],next[160005],to[160005],cnt;
 34 inline void addedge(int x,int y)
 35 {
 36     next[cnt]=h[x];
 37     to[cnt]=y;
 38     h[x]=cnt;
 39     cnt++;
 40 }
 41 int size[80005],hson[80005],dep[80005],f[80005];
 42 inline void bfs(int x,int fa)
 43 {
 44     int i;
 45     size[x]=1;
 46     for(i=h[x];i!=-1;i=next[i])
 47     {
 48         if(to[i]==fa)
 49         {
 50             continue;
 51         }
 52         dep[to[i]]=dep[x]+1;
 53         f[to[i]]=x;
 54         bfs(to[i],x);
 55         size[x]+=size[to[i]];
 56         if(size[to[i]]>size[hson[x]])
 57         {
 58             hson[x]=to[i];
 59         }
 60     }
 61 }
 62 int up[80005],first[80005],tim;
 63 inline void spfa(int x,int tt)
 64 {
 65     tim++;
 66     first[x]=tim;
 67     up[x]=tt;
 68     if(!hson[x])
 69     {
 70         return ;
 71     }
 72     spfa(hson[x],tt);
 73     int i;
 74     for(i=h[x];i!=-1;i=next[i])
 75     {
 76         if(to[i]==f[x]||to[i]==hson[x])
 77         {
 78             continue;
 79         }
 80         spfa(to[i],to[i]);
 81     }
 82 }
 83 inline int lca(int x,int y)
 84 {
 85     int res=0;
 86     while(up[x]!=up[y])
 87     {
 88         if(dep[up[x]]<dep[up[y]])
 89         {
 90             swap(x,y);
 91         }
 92         res+=query(first[x])-query(first[up[x]]-1);
 93         x=f[up[x]];
 94     }
 95     if(dep[x]>dep[y])
 96     {
 97         swap(x,y);
 98     }
 99     res+=query(first[y])-query(first[x]-1);
100     return res;
101 }
102 struct stu
103 {
104     int op,l,r,id,x;
105 };
106 stu a[240005];
107 int ans[80005];
108 int m[240005];
109 stu q1[240005],q2[240005];
110 inline void erfen(int l,int r,int sl,int sr)
111 {
112     if(sl>sr)
113     {
114         return ;
115     }
116     if(l==r)
117     {
118         int i;
119         for(i=sl;i<=sr;i++)
120         {
121             if(a[i].op!=2)
122             {
123                 continue;
124             }
125             ans[a[i].id]=l;
126         }
127         return ;
128     }
129     int i,mid=(l+r)>>1,k,cnt1=0,cnt2=0;
130     for(i=sl;i<=sr;i++)
131     {
132         if(a[i].op==0)
133         {
134             if(a[i].x<=mid)
135             {
136                 add(first[a[i].l],1);
137                 m[i]=0;
138             }
139             else
140             {
141                 m[i]=1;
142             }
143             continue;
144         }
145         if(a[i].op==1)
146         {
147             if(a[i].x<=mid)
148             {
149                 add(first[a[i].l],-1);
150                 m[i]=0;
151             }
152             else
153             {
154                 m[i]=1;
155             }
156             continue;
157         }
158         if(a[i].op==2)
159         {
160             k=lca(a[i].l,a[i].r);
161             if(k<a[i].x)
162             {
163                 a[i].x-=k;
164                 m[i]=1;
165             }
166             else
167             {
168                 m[i]=0;
169             }
170         }
171     }
172     for(i=sl;i<=sr;i++)
173     {
174         if(a[i].op==0)
175         {
176             if(a[i].x<=mid)
177             {
178                 add(first[a[i].l],-1);
179             }
180         }
181         if(a[i].op==1)
182         {
183             if(a[i].x<=mid)
184             {
185                 add(first[a[i].l],1);
186             }
187         }
188         if(m[i]==0)
189         {
190             cnt1++;
191             q1[cnt1]=a[i];
192         }
193         else
194         {
195             cnt2++;
196             q2[cnt2]=a[i];
197         }
198     }
199     for(i=1;i<=cnt1;i++)
200     {
201         a[sl+i-1]=q1[i];
202     }
203     for(i=1;i<=cnt2;i++)
204     {
205         a[sl+cnt1+i-1]=q2[i];
206     }
207     erfen(l,mid,sl,sl+cnt1-1);
208     erfen(mid+1,r,sl+cnt1,sr);
209 }
210 int p[80005];
211 int main()
212 {
213     memset(h,-1,sizeof(h));
214     memset(ans,0x3f,sizeof(ans));
215     n=read(),q=read();
216     int i,x,y,tail=0,k,o;
217     for(i=1;i<=n;i++)
218     {
219         x=read();
220         tail++;
221         a[tail].op=0,a[tail].l=i,a[tail].x=x;
222         p[i]=x;
223     }
224     for(i=1;i<n;i++)
225     {
226         x=read(),y=read();
227         addedge(x,y);
228         addedge(y,x);
229     }
230     dep[1]=1;
231     bfs(1,-1);
232     spfa(1,1);
233     for(i=1;i<=n;i++)
234     {
235         add(first[i],1);
236     }
237     for(i=1;i<=q;i++)
238     {
239         k=read(),x=read(),y=read();
240         if(k==0)
241         {
242             tail++;
243             a[tail].op=1;a[tail].l=x,a[tail].x=p[x];
244             tail++;
245             a[tail].op=0;a[tail].l=x;a[tail].x=y;
246             p[x]=y;
247         }
248         else
249         {
250             o=lca(x,y);
251             if(o<k)
252             {
253                 ans[i]=-1;
254                 continue;
255             }
256             k=o-k+1;
257             tail++;
258             a[tail].op=2,a[tail].l=x,a[tail].r=y,a[tail].x=k;
259             a[tail].id=i;
260         }
261     }
262     memset(data,0,sizeof(data));
263     erfen(0,100000000,1,tail);
264     for(i=1;i<=q;i++)
265     {
266         if(ans[i]==0x3f3f3f3f)
267         {
268             continue;
269         }
270         if(ans[i]==-1)
271         {
272             puts("invalid request!");
273         }
274         else
275         {
276             printf("%d\n",ans[i]);
277         }
278     }
279     return 0;
280 }
时间: 2024-09-17 04:56:23

bzoj1146整体二分+树链剖分+树状数组的相关文章

hdu 3966 Aragorn&#39;s Story(树链剖分+树状数组)

题目链接:hdu 3966 Aragorn's Story 题目大意:给定一个棵树,然后三种操作 Q x:查询节点x的值 I x y w:节点x到y这条路径上所有节点的值增加w D x y w:节点x到y这条路径上所有节点的值减少w 解题思路:树链剖分,用树状数组维护每个节点的值. #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include <cstring>

HDU 5044 (树链剖分+树状数组+点/边改查)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5044 题目大意:修改链上点,修改链上的边.查询所有点,查询所有边. 解题思路: 2014上海网赛的变态树链剖分模板题.将以往树链剖分的点&边修改和查询合在一起之后,难度上去不少. 第一个卡人点是读入优化. 第二个卡人点是树状数组.由于要查询所有点,如果使用线段树,每次都要扫到底层才能取出点值,必T无疑. 然后使用树状数组之后,树链剖分的点/边修改写法有些变动. 点查询变化不大. 边查询只要查询一下

Codeforces Round #425 (Div. 2) Problem D Misha, Grisha and Underground (Codeforces 832D) - 树链剖分 - 树状数组

Misha and Grisha are funny boys, so they like to use new underground. The underground has n stations connected with n - 1 routes so that each route connects two stations, and it is possible to reach every station from any other. The boys decided to h

POJ 2763 Housewife Wind(树链剖分+树状数组)

[题目链接] http://poj.org/problem?id=2763 [题目大意] 在一棵树上,给出一些边的边长,有修改边的边长的操作, 询问每次从当前点到目标点的最短距离 [题解] 树链剖分之后,相当于树状数组的单点更新和区间查询, 注意边权转点权之后链操作不覆盖deep最浅的点,这里容易出错 [代码] #include <cstdio> #include <cstring> #include <algorithm> using namespace std; c

【LuoguP3038/[USACO11DEC]牧草种植Grass Planting】树链剖分+树状数组【树状数组的区间修改与区间查询】

模拟题,可以用树链剖分+线段树维护. 但是学了一个厉害的..树状数组的区间修改与区间查询.. 分割线里面的是转载的: -------------------------------------------------------------------------------- [ 3 ]  上面都不是重点--重点是树状数组的区间修改+区间查询 这个很好玩 其实也挺简单 首先依旧是引入delta数组 delta[i]表示区间 [i, n] 的共同增量 于是修改区间 [l, r] 时修改 delt

(简单) POJ 3321 Apple Tree,树链剖分+树状数组。

Description There is an apple tree outside of kaka's house. Every autumn, a lot of apples will grow in the tree. Kaka likes apple very much, so he has been carefully nurturing the big apple tree. The tree has N forks which are connected by branches.

Codeforces Round #425 (Div. 2) D 树链剖分 + 树状数组维护区间

一看就知道 可以LCA判断做 也可以树链剖分拿头暴力 然而快速读入和线段树维护区间会T70 于是只能LCA? 线段树的常数不小 于是需要另外一种办法来进行区间加减和查询区间和 就是使用树状数组 这个题的代码 #include<iostream> #include<cstdio> #include<cmath> #include<algorithm> #include<vector> #include<cstring> using na

BZOJ 1146: [CTSC2008]网络管理Network( 树链剖分 + 树状数组套主席树 )

树链剖分完就成了一道主席树裸题了, 每次树链剖分找出相应区间然后用BIT+(可持久化)权值线段树就可以完成计数. 但是空间问题很严重....在修改时不必要的就不要新建, 直接修改原来的..详见代码. 时间复杂度O(N*log^3(N)) ---------------------------------------------------------------------------- #include<cstdio> #include<cstring> #include<

树链剖分 树的统计

/*题目描述 Description一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w. 我们将以下面的形式来要求你对这棵树完成一些操作: I.                    CHANGE u t : 把结点u的权值改为tII.                 QMAX u v: 询问从点u到点v的路径上的节点的最大权值III.               QSUM u v: 询问从点u到点v的路径上的节点的权值和 注意:从点u到点v的路径上的节点包括u和v本身 输入描述 In