(离线树链剖分)HDU - 6162 Ch’s gift

题意:

一颗树,q次查询从u到v路径上所有权值在l到r之间的和。

分析:

一开始想写树上主席树,然后感觉内存不够就放弃。

然后想了一个小时,然后发现,询问似曾相识,回忆起一题。

然后发现直接离线搞就行了。

确切的说这题和HDU4417是完全一样的。

将询问排序,然后把小的点加进去,然后查询。

至于l和r,将两个分开分别处理就行了嘛。

算是比较裸的题了,居然想了这么久。

 

(哇,后来发现主席树内存是够的。。

可以做,与树链第K大类似,一个数组统计区间内的个数,再开一个longlong保存和即可,

用lca进行二分就行啦。

这样复杂度才nlogn,比树剖快撒。

 

(哇,比赛的时候同学暴力LCA就A了,而且才700+ms,哇

 

代码:

  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdio>
  4 #include <algorithm>
  5 #include <vector>
  6 
  7 using namespace std;
  8 
  9 const int maxn=100010;
 10 
 11 int n,q,m;
 12 
 13 struct Edge
 14 {
 15     int to,next;
 16 } edge[maxn<<1];
 17 int head[maxn],tot;
 18 int top[maxn];
 19 int fa[maxn];
 20 int deep[maxn];
 21 int num[maxn];
 22 int p[maxn];
 23 int fp[maxn];
 24 int son[maxn];
 25 int pos;
 26 
 27 struct P
 28 {
 29     int val,u;
 30     bool operator<(const P a)const
 31     {
 32         return val<a.val;
 33     }
 34 };
 35 P val[maxn];
 36 
 37 
 38 void addedge(int u,int v)
 39 {
 40     edge[tot].to = v;
 41     edge[tot].next=head[u];
 42     head[u]=tot++;
 43 }
 44 
 45 void dfs1(int u,int pre,int d)
 46 {
 47     deep[u]=d;
 48     fa[u]=pre;
 49     num[u]=1;
 50     for(int i=head[u]; i!=-1; i=edge[i].next)
 51     {
 52         int v = edge[i].to;
 53         if(v!=pre)
 54         {
 55             dfs1(v,u,d+1);
 56             num[u]+=num[v];
 57             if(son[u]==-1||num[v]>num[son[u]])son[u]=v;
 58         }
 59     }
 60 }
 61 
 62 void getpos(int u,int sp)
 63 {
 64     top[u]=sp;
 65     p[u]=pos++;
 66     fp[p[u]]=u;
 67     if(son[u]==-1)return ;
 68     getpos(son[u],sp);
 69     for(int i=head[u]; i!=-1; i=edge[i].next)
 70     {
 71         int v = edge[i].to;
 72         if(v!=son[u]&&v!=fa[u])getpos(v,v);
 73     }
 74 }
 75 
 76 struct Node
 77 {
 78     int left, right;
 79     long long sum;
 80 } node[maxn<<2];
 81 
 82 
 83 void build(int n,int left,int right)
 84 {
 85     node[n].left=left,node[n].right=right;
 86     node[n].sum=0;
 87     if(left==right)return ;
 88     int mid = (left+right)>>1;
 89     build(n<<1,left,mid);
 90     build(n<<1|1,mid+1,right);
 91 }
 92 
 93 void push_up(int n)
 94 {
 95     node[n].sum=node[n<<1].sum+node[n<<1|1].sum;
 96 }
 97 
 98 void update(int n,int pos,long long val)
 99 {
100     if(node[n].left==node[n].right)
101     {
102         node[n].sum+=val;//wait
103         return ;
104     }
105     int mid = (node[n].left+node[n].right)>>1;
106     if(pos<=mid)update(n<<1,pos,val);
107     else update(n<<1|1,pos,val);
108     push_up(n);
109 }
110 
111 long long query(int n,int left,int right)
112 {
113     if(left<=node[n].left&&node[n].right<=right)
114     {
115         return node[n].sum;
116     }
117     int mid = (node[n].left+node[n].right)>>1;
118     long long sum=0;
119     if(mid>=left)sum+=query(n<<1,left,right);
120     if(mid<right)sum+=query(n<<1|1,left,right);
121     return sum;
122 }
123 
124 
125 long long findSum(int x,int y)
126 {
127     long long tmp = 0;
128     while(top[x]!=top[y])
129     {
130         if(deep[top[x]]<deep[top[y]])swap(x,y);
131         tmp +=query(1,p[top[x]],p[x]);
132         x=fa[top[x]];
133     }
134     if(deep[x]>deep[y])swap(x,y);
135     tmp+=query(1,p[x],p[y]);
136     return tmp;
137 }
138 
139 struct Q
140 {
141     int u,v,x;
142     int i;
143 };
144 vector<Q> pl,pr;
145 
146 bool cmp(Q a,Q b)
147 {
148     return a.x<b.x;
149 }
150 
151 long long ansl[maxn],ansr[maxn];
152 
153 
154 void init()
155 {
156     tot=0;
157     memset(head,-1,sizeof(head));
158     pos=0;
159     memset(son,-1,sizeof(son));
160     pl.clear(),pr.clear();
161 }
162 
163 
164 int main()
165 {
166     while(~scanf("%d%d",&n,&q))
167     {
168         init();
169         for(int i=1; i<=n; i++)
170         {
171             scanf("%d",&val[i].val);
172             val[i].u=i;
173         }
174         sort(val+1,val+n+1);
175         for(int i=0; i<n-1; i++)
176         {
177             int u,v;
178             scanf("%d%d",&u,&v);
179             addedge(u,v);
180             addedge(v,u);
181         }
182         dfs1(1,0,0);
183         getpos(1,1);
184         for(int i=0; i<q; i++)
185         {
186             int u,v,a,b;
187             scanf("%d%d%d%d",&u,&v,&a,&b);
188             pl.push_back(Q{u,v,a,i});
189             pr.push_back(Q{u,v,b,i});
190         }
191         sort(pl.begin(),pl.end(),cmp);
192         sort(pr.begin(),pr.end(),cmp);
193         int l = 1;
194         build(1,0,pos-1);
195         for(int i=0; i<pl.size(); i++)
196         {
197             while(val[l].val<pl[i].x&&l<=n)
198             {
199                 update(1,p[val[l].u],val[l].val);
200                 l++;
201             }
202             ansl[pl[i].i]=findSum(pl[i].u,pl[i].v);
203         }
204         build(1,0,pos-1);
205         l=1;
206         for(int i=0; i<pr.size(); i++)
207         {
208             while(val[l].val<=pr[i].x&&l<=n)
209             {
210                 update(1,p[val[l].u],val[l].val);
211                 l++;
212             }
213             ansr[pr[i].i]=findSum(pr[i].u,pr[i].v);
214         }
215         for(int i=0;i<q-1;i++){
216             printf("%lld ",ansr[i]-ansl[i]);
217         }
218         printf("%lld\n",ansr[q-1]-ansl[q-1]);
219     }
220     return 0;
221 }

 

posted @ 2017-08-22 20:41  tak_fate  阅读(261)  评论(0编辑  收藏  举报