BZOJ4009 [HNOI2015] 接水果

Posted goldgenius

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ4009 [HNOI2015] 接水果相关的知识,希望对你有一定的参考价值。

【问题描述】

风见幽香非常喜欢玩一个叫做 osu!的游戏,其中她最喜欢玩的模式就是接水果。由于她已经DT FC 了The big black, 她觉得这个游戏太简单了,于是发明了一个更加难的版本。首先有一个地图,是一棵由 n 个顶点、n-1 条边组成的树(例如图 1给出的树包含 8 个顶点、7 条边)。这颗树上有 P 个盘子,每个盘子实际上是一条路径(例如图 1 中顶点 6 到顶点 8 的路径),并且每个盘子还有一个权值。第 i 个盘子就是顶点a _ i到顶点b _ i的路径(由于是树,所以从a _ i到b _ i 的路径是唯一的), 权值为c _ i。接下来依次会有Q个水果掉下来,每个水果本质上也是一条路径,第i 个水果是从顶点 u _ i 到顶点v _ i 的路径。
幽香每次需要选择一个盘子去接当前的水果:一个盘子能接住一个水果,当且仅当盘子的路径是水果的路径的子路径(例如 图1中从 3到7 的路径是从1到8的路径的子路径)。
这里规定:从a 到b的路径与从b到 a的路径是同一条路径。当然为了提高难度,对于第 i 个水果,你需要选择能接住它的所有盘子中,权值第 k _ i 小的那个盘子,每个盘子可重复使用(没有使用次数的上限:一个盘子接完一个水果后,后面还可继续接其他水果,只要它是水果路径的子路径)。幽香认为这个游 戏很难,你能轻松解决给她看吗?

【输入格式】

第一行三个数 n和P 和Q,表示树的大小和盘子的个数和水果的个数。
接下来n-1 行,每行两个数 a、b,表示树上的a和b 之间有一条边。树中顶点按1到 n标号。
接下来 P 行,每行三个数 a、b、c,表示路径为 a 到 b、权值为 c 的盘子,其中0≤c≤10^9,a不等于b。
接下来Q行,每行三个数 u、v、k,表示路径为 u到 v的水果,其中 u不等于v,你需要选择第 k小的盘子,第k 小一定存在。

【输出格式】

对于每个果子,输出一行表示选择的盘子的权值。

【输入样例】

10 10 10
1 2
2 3
3 4
4 5
5 6
6 7
7 8
8 9
9 10
3 2 217394434
10 7 13022269
6 7 283254485
6 8 333042360
4 6 442139372
8 3 225045590
10 4 922205209
10 8 808296330
9 2 486331361
4 9 551176338
1 8 5
3 8 3
3 8 4
1 8 3
4 8 1
2 3 1
2 3 1
2 3 1
2 4 1
1 4 1

【输出样例】

442139372
333042360
442139372
283254485
283254485
217394434
217394434
217394434
217394434
217394434

【数据范围】

对于100%数据n,P,Q<=40000;

正解:dfs序加整体二分

解题报告:

动 态区间第k大,显然是整体二分,然而我因为一个地方’b1‘打成了‘i’结果调了一天,心好痛。。。。用dfs序判断点与点之间的关系,对于没一个盘子, 我们可以把它所覆盖的区间用dfs序表示出来,然后再把每个覆盖的两个区间拆成两个点和一个区间,一个点带一个区间表示插入,一个点带一个区间表示删除, 把读入的询问也变成两个点,按前面一个点的dfs序排序,即可保证左边在覆盖区域之中,后面一个点之间用树状数组维护,然后就是基本的整体二分了。

  1 #include <iostream>
  2 #include <iomanip>
  3 #include <cstdlib>
  4 #include <cstdio>
  5 #include <cmath>
  6 #include <algorithm>
  7 #include <string>
  8 #include <cstring>
  9 #define RG register
 10 #define File(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
 11 const int N = 1000000;
 12 const int M = 500000;
 13 const int inf = 21474830;
 14 using namespace std;
 15 int gi(){
 16     char ch=getchar();int x=0;
 17     while(ch<0 || ch>9)ch=getchar();
 18     while (ch>=0 && ch<=9) {x=x*10+ch-0;ch=getchar();}
 19     return x;
 20 }
 21 int tt,n,p,q,nn[N][2],head[M],l,r,dfn[M],f[M],num[M],cnt,son[M];
 22 int id[N],ans[N],bis[N],dep[N],siz[N],fa[N],top[N],sum[M],cd[N][20];
 23 struct date{int l,r,z,y,s,x;}d[N],g[N],a1[M],a2[M];
 24 struct dote{int l,z,y,s,c;}c[M];
 25 int cmp(date a,date b){return a.s<b.s;}
 26 int cop(dote a,dote b){if (a.l==b.l) return a.s<b.s;return a.l<b.l;}
 27 void update(int xh,int x){while(xh<=n){f[xh]+=x;xh+=xh&(-xh);}return;}
 28 int query(int xh){int s=0;while(xh){s+=f[xh];xh-=xh&(-xh);}return s;}
 29 int lca(int u,int v){
 30     while(top[u]!=top[v]){if (dep[top[u]]>=dep[top[v]]) u=fa[top[u]]; else v=fa[top[v]];}
 31     return dep[u]<dep[v]?u:v;}
 32 int jump(int xh,int dis){
 33     for (RG int i=19; i>=0; i--)
 34         if (dep[cd[xh][i]]>=dis)
 35             xh=cd[xh][i];
 36     return xh;}
 37 
 38 void dfs1(int xh,int ff){
 39     dep[xh]=dep[ff]+1,siz[xh]=1,fa[xh]=ff;
 40     for (RG int i=head[xh]; i; i=nn[i][0]){
 41         if (nn[i][1]==ff) continue;
 42         dfs1(nn[i][1],xh);siz[xh]+=siz[nn[i][1]];
 43         if (siz[nn[i][1]]>siz[bis[xh]]) bis[xh]=nn[i][1];}
 44     return;}
 45 
 46 void dfs2(int xh,int tp){
 47     top[xh]=tp;
 48     if (bis[xh]) dfs2(bis[xh],tp);
 49     for (RG int i=head[xh]; i; i=nn[i][0]){
 50         if (nn[i][1]==bis[xh] || nn[i][1]==fa[xh]) continue;
 51         dfs2(nn[i][1],nn[i][1]);}
 52     return;}
 53 
 54 void dfs(int xh,int fa){
 55     dfn[xh]=++cnt;
 56     for (RG int i=head[xh]; i; i=nn[i][0]){
 57         if (nn[i][1]==fa) continue;dfs(nn[i][1],xh);}
 58     son[xh]=cnt;return;}
 59 
 60 void cdq(int l,int r,int ql,int qr){
 61     if (ql>qr) return;RG int i,j,t=0,b1=0,b2=0,mid=(l+r)>>1;
 62     if (l==r){for (i=ql; i<=qr; i++) ans[g[i].x]=d[l].s;return;}
 63     for (i=l; i<=mid; i++) c[++t]=(dote){d[i].l,d[i].z,d[i].y,0,1},c[++t]=(dote){d[i].r,d[i].z,d[i].y,inf,-1};
 64     for (i=ql; i<=qr; i++) c[++t]=(dote){g[i].l,g[i].r,0,i,0};
 65     sort(c+1,c+t+1,cop);
 66     for (i=1; i<=t; i++)
 67         if (c[i].s<=qr && c[i].s>=ql)
 68             sum[c[i].s]=query(c[i].z);
 69         else
 70             update(c[i].z,c[i].c),update(c[i].y+1,-c[i].c);
 71     for (i=ql; i<=qr; i++)
 72         if (sum[i]>=g[i].s) a1[++b1]=g[i];
 73         else a2[++b2]=g[i],a2[b2].s-=sum[i];
 74     t=ql+b1-1;
 75     for (i=ql,j=1; i<=t; j++,i++) g[i]=a1[j];
 76     for (i=t+1,j=1; i<=qr; j++,i++) g[i]=a2[j];
 77     cdq(l,mid,ql,ql+b1-1);
 78     cdq(mid+1,r,ql+b1,qr);
 79     return;
 80 }
 81 
 82 int main(){
 83     File("a");
 84     n=gi(),p=gi(),q=gi();RG int i;
 85     for (i=1; i<n; i++){
 86         l=gi(),r=gi();
 87         nn[++tt][1]=l,nn[tt][0]=head[r],head[r]=tt;
 88         nn[++tt][1]=r,nn[tt][0]=head[l],head[l]=tt;
 89     }
 90     RG int t=0,u,v,k,j;
 91     dfs(1,0),dfs1(1,0),dfs2(1,1);
 92     for (i=1; i<=n; i++) cd[i][0]=fa[i];
 93     for (i=1; i<20; i++) for (j=1; j<=n; j++) cd[j][i]=cd[cd[j][i-1]][i-1];
 94     for (i=1; i<=p; i++){
 95         u=gi(),v=gi(),k=gi();
 96         if (dfn[u]>dfn[v]) j=u,u=v,v=j;
 97         if (u!=lca(u,v)) d[++t]=(date){dfn[u],son[u],dfn[v],son[v],k,0};
 98         else{
 99             tt=jump(v,dep[u]+1);
100             d[++t]=(date){1,dfn[tt]-1,dfn[v],son[v],k,0};
101             if (son[tt]<n) d[++t]=(date){dfn[v],son[v],son[tt]+1,n,k,0};
102         }
103     }
104     for (i=1; i<=q; i++){
105         u=gi(),v=gi(),k=gi();if (dfn[u]>dfn[v]) j=u,u=v,v=j;
106         g[i]=(date){dfn[u],dfn[v],0,0,k,i};
107     }
108     sort(d+1,d+t+1,cmp);
109     cdq(1,t,1,q);
110     for (i=1; i<=q; i++) printf("%d\n",ans[i]);
111     return 0;
112 }

 

以上是关于BZOJ4009 [HNOI2015] 接水果的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ4009 HNOI2015 接水果

BZOJ4009 [HNOI2015]接水果

bzoj4009 [HNOI2015]接水果

BZOJ4009 [HNOI2015] 接水果

BZOJ4009[HNOI2015]接水果 DFS序+整体二分+扫描线+树状数组

BZOJ4009 & 洛谷3242 & LOJ2113:[HNOI2015]接水果——题解