题目名称 1957. [HNOI 2015]接水果
输入输出 fruit_hnoi2015.in/out
难度等级 ★★★★
时间限制 6000 ms (6 s)
内存限制 512 MiB
测试数据 10
题目来源 Gravatarcstdio 于2015-04-27加入
开放分组 全部用户
提交状态
分类标签
分享题解
通过:31, 提交:91, 通过率:34.07%
Gravatar 100 0.867 s 14.11 MiB C++
GravatarLPA 100 0.875 s 29.36 MiB C++
GravatarGintoki 100 0.972 s 8.23 MiB C++
Gravatar支羽 100 1.008 s 8.19 MiB C++
Gravatartest 100 1.138 s 8.86 MiB C++
Gravatartest 100 1.145 s 8.86 MiB C++
Gravatarchenhongkan 100 1.269 s 9.01 MiB C++
Gravatarppfish 100 1.359 s 9.79 MiB C++
GravatarLadyLex 100 1.370 s 12.07 MiB C++
GravatarNawox 100 1.837 s 76.02 MiB C++
本题关联比赛
4043级2023省选模拟赛3
关于 接水果 的近10条评论(全部评论)
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <queue>
#define inf (1<<30)
#define il inline
#define RG register
#define LL long long
#define lowbit(o) o & (-o)
#define N 40001
using namespace std;
struct ed{int nxt,to;}e[N*2];int head[N],tot;
int id[N],top[N],BL[N],sz[N],fa[N],deep[N],hson[N],w[N];
int n,P,Q,idn;
inline int read() {
int x=0;
char ch=getchar();
while(ch<'0'||ch>'9') ch=getchar();
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x;
}
il void add(RG int u,RG int v){e[tot].nxt=head[u];e[tot].to=v;head[u]=tot++;}
il void ADD(RG int u,RG int v){add(u,v),add(v,u);}
il void dfs1(RG int u,RG int faa){
deep[u]=deep[faa]+1,sz[u]=1;fa[u]=faa;
for(RG int i=head[u];i!=-1;i=e[i].nxt)if(e[i].to!=faa){
RG int v=e[i].to;dfs1(v,u);
sz[u]+=sz[v];if(sz[hson[u]]<sz[v])hson[u]=v;
}
}
il void dfs2(RG int u,RG int toop){top[u]=toop;
id[u]=++idn;BL[idn]=u;if(hson[u])dfs2(hson[u],toop);
for(RG int i=head[u];i!=-1;i=e[i].nxt)
if(e[i].to!=fa[u]&&e[i].to!=hson[u])
dfs2(e[i].to,e[i].to);w[u]=idn;
}
il int LCA(RG int x,RG int y){
while(top[x]!=top[y]){
if(deep[top[x]]<deep[top[y]])swap(x,y);
x=fa[top[x]];
}if(deep[x]>deep[y])swap(x,y);
return x;
}
il int gogogo(int x,int y){RG int ll=0;
while(top[x]!=top[y]){
if(deep[top[x]]<deep[top[y]])swap(x,y);
ll=top[x],x=fa[top[x]];
}if(deep[x]>deep[y])swap(x,y);
return x==y?ll:BL[id[x]+1];
}
struct matrix{
int x,xx,y,yy,k;
matrix() {}
matrix(int X,int XX,int Y,int YY,int K):x(X),xx(XX),y(Y),yy(YY),k(K) {}
}p[N*2];int cnt;
struct node{
int x,y,k,id;
node() {}
node(int _x,int _y,int _k,int i):x(_x),y(_y),k(_k),id(i) {}
}ff[N],quer[N],quel[N];
int tree[N],ans[N];
il void Add(int x,int y){for(RG int i=x;i<=n;i+=lowbit(i))tree[i]+=y;}
int Query(int x){int s=0;for(RG int i=x;i;i-=lowbit(i))s+=tree[i];return s;}
il bool comp(const matrix & a,const matrix & b){return a.k<b.k;}
struct ha{
int x,y,yy,v,kind;
ha() {}
ha(int a,int b,int c,int d,int e):x(a),y(b),yy(c),v(d),kind(e) {}
}que[N*3];int sum[N];
il bool Comp(const ha & a,const ha & b){return a.x==b.x?a.kind<b.kind:a.x<b.x;}
il void solve(RG int h,RG int t,RG int l,RG int r){
if(t<h)return;
if(l==r){
for(int i=h;i<=t;++i)ans[ff[i].id]=p[l].k;
return;
}RG int mid=(l+r)>>1;int ss=0;
for(RG int i=l;i<=mid;++i){
que[++ss]=ha(p[i].x,p[i].y,p[i].yy,1,0);
que[++ss]=ha(p[i].xx,p[i].y,p[i].yy,-1,n+1);
}for(RG int i=h;i<=t;++i)
que[++ss]=ha(ff[i].x,ff[i].y,0,0,i);
sort(que+1,que+ss+1,Comp);memset(tree,0,sizeof(tree));
for(RG int i=1;i<=ss;++i)
if(que[i].kind>=h&&que[i].kind<=t)
sum[que[i].kind]=Query(que[i].y);
else Add(que[i].y,que[i].v),Add(que[i].yy+1,-que[i].v);
RG int L=0,R=0;
for(RG int i=h;i<=t;++i){
if(sum[i]>=ff[i].k)quel[++L]=ff[i];
else quer[++R]=ff[i],quer[R].k-=sum[i];
}for(RG int i=1;i<=L;++i)ff[i+h-1]=quel[i];
for(RG int i=1;i<=R;++i)ff[L+h+i-1]=quer[i];
solve(h,h+L-1,l,mid);solve(h+L,t,mid+1,r);
}
int main(){
freopen("fruit_hnoi2015.in","r",stdin);
freopen("fruit_hnoi2015.out","w",stdout);
memset(head,-1,sizeof(head));
n=read(),P=read(),Q=read();int u,v;
for(RG int i=1;i<n;++i)u=read(),v=read(),ADD(u,v);
dfs1(1,1),dfs2(1,1);
for(RG int i=1;i<=P;++i){
RG int a,b,c;a=read(),b=read(),c=read();
RG int lca=LCA(a,b);if(id[a]>id[b])swap(a,b);
if(lca==a){RG int mm=gogogo(a,b);
if(id[mm]>1)p[++cnt]=matrix(1,id[mm]-1,id[b],w[b],c);
if(w[mm]+1<=n)p[++cnt]=matrix(id[b],w[b],w[mm]+1,n,c);
}
else p[++cnt]=matrix(id[a],w[a],id[b],w[b],c);
}
for(RG int i=1;i<=Q;++i){
RG int u,v,k;u=read(),v=read(),k=read();
if(id[u]>id[v])swap(u,v);
ff[i]=node(id[u],id[v],k,i);
}sort(p+1,p+cnt+1,comp);solve(1,Q,1,cnt);
for(RG int i=1;i<=Q;++i)cout<<ans[i]<<"\n";
return 0;
}
Gravatartest
2017-07-14 15:15 1楼

1957. [HNOI 2015]接水果

★★★★   输入文件:fruit_hnoi2015.in   输出文件:fruit_hnoi2015.out   简单对比
时间限制:6 s   内存限制:512 MiB

【题目描述】

风见幽香非常喜欢玩一个叫做 $osu!$ 的游戏,其中她最喜欢玩的模式就是接水果。由于她已经 $DT$ $FC$ 了 $The\ big\ black$,她觉得这个游戏太简单了,于是发明了一个更加难的版本。

首先有一个地图,是一棵由 $n$ 个顶点,$n-1$ 条边组成的树。

这颗树上有 $p$ 个盘子,每个盘子实际上是一条路径,并且每个盘子还有一个权值。第 $i$ 个盘子就是顶点 $a_i$ 到顶点 $b_i$ 的路径(由于是树,所以从 $a_i$ 到 $b_i$ 的路径是唯一的),权值为 $c_i$。

接下来依次会有 $q$ 个水果掉下来,每个水果本质上也是一条路径,第 $i$ 个水果是从顶点 $u_i$ 到顶点 $v_i$ 的路径。

幽香每次需要选择一个盘子去接当前的水果:一个盘子能接住一个水果,当且仅当盘子的路径是水果的路径的子路径。这里规定:从 $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$ 的盘子,其中 $a \neq b$。

接下来 $q$ 行,每行三个数 $u,v,k$,表示路径为 $u$ 到 $v$ 的水果,其中 $u \neq v$,你需要选择第 $k$ 小的盘子,第 $k$ 小一定存在。

【输出格式】

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

【样例1输入】

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

【样例1输出】

442139372
333042360
442139372
283254485
283254485
217394434
217394434
217394434
217394434
217394434

【样例2】

点击下载样例2

【数据规模与约定】

对于 $20\%$ 的数据,$1\leq n,p,q \leq 3\times 10^3$;

对于另 $30\%$ 的数据,$1\leq n,p,q \leq 4\times 10^4$,树是一条链;

对于 $100\%$ 的数据,$1\leq n,p,q \leq 4\times 10^4$,$0 \le c \le 10^9$。