• [BZOJ4009][HNOI2015]接水果(整体二分)


    [HNOI2015]接水果

    时间限制:60s      空间限制:512MB

    题目描述

    风见幽香非常喜欢玩一个叫做 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 
     

    提示

    N,P,Q<=40000。 


    题目来源

    没有写明来源

    类似HNOI2017的影魔,思想是把对象映射到平面上。

    代码用时:1.5h。非常裸,整体二分加扫描线,树状数组代替线段树既省时有省力。

     1 #include<cstdio>
     2 #include<algorithm>
     3 #define rep(i,l,r) for (int i=l; i<=r; i++)
     4 #define For(i,x) for (int i=h[x],k; i; i=nxt[i])
     5 using namespace std;
     6 
     7 const int N=80100;
     8 int n,m,q,a,b,c,k,u,cnt,fa[N][18],dfn[N],tim,lst[N],v[N],dep[N],ans[N],sum[N],nxt[N],h[N],to[N],tot;
     9 struct P{ int x1,x2,y1,y2,v; }p[N];
    10 struct D{ int x,y1,y2,v,id; }d[N];
    11 struct Q{int x,y,k,id; }pnt[N],t1[N],t2[N];
    12 bool operator <(P a,P b){ return a.v<b.v; }
    13 bool operator <(D a,D b){ return a.x==b.x ? a.id<b.id : a.x<b.x; }
    14 void add(int u,int v){ nxt[++tot]=h[u]; h[u]=tot; to[tot]=v; }
    15 int que(int x){ int res=0; for (; x; x-=(x&(-x))) res+=v[x]; return res; }
    16 
    17 void mdf(int l,int r,int k){
    18     for (int i=l; i<=n; i+=(i&(-i))) v[i]+=k;
    19     for (int i=r+1; i<=n; i+=(i&(-i))) v[i]-=k;
    20 }
    21 
    22 void dfs(int x){
    23     dfn[x]=++tim;
    24     rep(i,1,17) fa[x][i]=fa[fa[x][i-1]][i-1];
    25     For(i,x) if ((k=to[i])!=fa[x][0]) fa[k][0]=x,dep[k]=dep[x]+1,dfs(k);
    26     lst[x]=tim;
    27 }
    28 
    29 int go(int a,int h){ for (int i=16; ~i; i--) if (h&(1<<i)) a=fa[a][i]; return a; }
    30 
    31 int lca(int a,int b){
    32     if (dep[a]<dep[b]) swap(a,b);
    33     a=go(a,dep[a]-dep[b]);
    34     if (a==b) return a;
    35     for (int i=16; ~i; i--) if (fa[a][i]!=fa[b][i]) a=fa[a][i],b=fa[b][i];
    36     return fa[a][0];
    37 }
    38 
    39 void solve(int l,int r,int st,int ed){
    40     if (st>ed) return;
    41     if (l==r){ rep(i,st,ed) ans[pnt[i].id]=p[l].v; return; }
    42     int mid=(l+r)>>1,sz=0;
    43     rep(i,l,mid){
    44         d[++sz]=(D){p[i].x1,p[i].y1,p[i].y2,1,0};
    45         d[++sz]=(D){p[i].x2,p[i].y1,p[i].y2,-1,n+1};
    46     }
    47     rep(i,st,ed) d[++sz]=(D){pnt[i].x,pnt[i].y,0,0,i};
    48     sort(d+1,d+sz+1);
    49     rep(i,1,sz)
    50         if (st<=d[i].id && d[i].id<=ed) sum[d[i].id]=que(d[i].y1);
    51             else mdf(d[i].y1,d[i].y2,d[i].v);
    52     int a=0,b=0;
    53     rep(i,st,ed)
    54         if (sum[i]>=pnt[i].k) t1[++a]=pnt[i];
    55         else t2[++b]=(Q){pnt[i].x,pnt[i].y,pnt[i].k-sum[i],pnt[i].id};
    56     rep(i,st,st+a-1) pnt[i]=t1[i-st+1];
    57     rep(i,st+a,ed) pnt[i]=t2[i-st-a+1];
    58     solve(l,mid,st,st+a-1); solve(mid+1,r,st+a,ed);
    59 }
    60 
    61 int main(){
    62     freopen("bzoj4009.in","r",stdin);
    63     freopen("bzoj4009.out","w",stdout);
    64     scanf("%d%d%d",&n,&m,&q);
    65     rep(i,1,n-1) scanf("%d%d",&a,&b),add(a,b),add(b,a);
    66     dfs(1);
    67     rep(i,1,m){
    68         scanf("%d%d%d",&a,&b,&c); u=lca(a,b);
    69         if (dfn[a]>dfn[b]) swap(a,b);
    70         if (u!=a) p[++cnt]=(P){dfn[a],lst[a],dfn[b],lst[b],c};
    71         else{
    72             int w=go(b,dep[b]-dep[a]-1);
    73             p[++cnt]=(P){1,dfn[w]-1,dfn[b],lst[b],c};
    74             if (lst[w]<n) p[++cnt]=(P){dfn[b],lst[b],lst[w]+1,n,c};
    75         }
    76     }
    77     sort(p+1,p+cnt+1);
    78     rep(i,1,q){
    79         scanf("%d%d%d",&a,&b,&k);
    80         if (dfn[a]>dfn[b]) swap(a,b);
    81         pnt[i]=(Q){dfn[a],dfn[b],k,i};
    82     }
    83     solve(1,cnt,1,q);
    84     rep(i,1,q) printf("%d
    ",ans[i]);
    85     return 0;
    86 }
  • 相关阅读:
    2017.3.22上午
    2017.3.21下午
    2017.3.21上午
    git上传到阿里云code
    spring+ibatis整合
    Aop资料整理
    java加密算法之AES小记
    单例的八种写法:推荐静态内部类和枚举
    dubbo入门示例
    自定义注解判空简单示例
  • 原文地址:https://www.cnblogs.com/HocRiser/p/8325063.html
Copyright © 2020-2023  润新知