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 }