• 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
    ",ans[i]);
    111     return 0;
    112 }
  • 相关阅读:
    .net调用存储过程详解
    SQL SERVER 与ACCESS、EXCEL的数据转换
    dedecms 织梦 获取文章链接地址
    用SQL语句添加删除修改字段、一些表与字段的基本操作、数据库备份等
    SQL Server触发器创建、删除、修改、查看示例步骤
    (后缀数组模板)BZOJ1031[JSOI2007]字符加密Cipher
    LOJ2055「TJOI / HEOI2016」排序
    BZOJ1096[ZJOI2007]仓库建设
    POI2011Meteors
    数位dp(1)
  • 原文地址:https://www.cnblogs.com/cjk2001/p/6372046.html
Copyright © 2020-2023  润新知