• [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 小的那个盘子,每个盘子可重复使用(没有使用次数的上限:一个盘子接完一个水果后,后面还可继续接其他水果,只要它是水果路径的子路径)。幽香认为这个游戏很难,你能轻松解决给她看吗? < width="395" height="212" alt="" />

    输入输出格式

    输入格式:

    第一行三个数 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 小一定存在。

    输出格式:

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

    输入输出样例

    输入样例#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
    http://www.cnblogs.com/NaVi-Awson/p/8150418.html
      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<cmath>
      5 #include<algorithm>
      6 using namespace std;
      7 struct Node
      8 {
      9   int next,to;
     10 }edge[100001];
     11 struct FFF
     12 {
     13   int x1,x2,y1,y2,k;
     14 }opt[100001];
     15 struct ZYYS
     16 {
     17   int x,y,k,id;
     18 }query[80001],qa[80001],qb[80001];
     19 struct ALUGE
     20 {
     21   int x,y1,y2,d,id;
     22 }event[200001];
     23 int head[80001],num,dfn[80001],cnt,size[80001],n,son[80001],dep[80001],pa[80001],last[80001],top[80001];
     24 int c[80001],ans[80001],sum[80001],p,q,cntp;
     25 bool cmpe(ALUGE a,ALUGE b)
     26 {
     27   if (a.x==b.x) return a.id<b.id;
     28   return a.x<b.x;
     29 }
     30 bool cmpp(FFF a,FFF b)
     31 {
     32   return a.k<b.k;
     33 }
     34 bool cmpq(ZYYS a,ZYYS b)
     35 {
     36   return a.x<b.x;
     37 }
     38 void add(int u,int v)
     39 {
     40   num++;
     41   edge[num].next=head[u];
     42   head[u]=num;
     43   edge[num].to=v;
     44 }
     45 void dfs1(int x,int fa)
     46 {int i;
     47   size[x]=1;
     48   son[x]=0;
     49   for (i=head[x];i;i=edge[i].next)
     50     {
     51       int v=edge[i].to;
     52       if (v!=fa)
     53     {
     54       dep[v]=dep[x]+1;pa[v]=x;
     55       dfs1(v,x);
     56       size[x]+=size[v];
     57       if (size[v]>=size[son[x]]) son[x]=v;
     58     }
     59     }
     60   last[x]=cnt;
     61 }
     62 void dfs2(int x,int tp,int fa)
     63 {int i;
     64   top[x]=tp;
     65   dfn[x]=++cnt;
     66   if (son[x]) dfs2(son[x],tp,x);
     67   for (i=head[x];i;i=edge[i].next)
     68     {
     69       int v=edge[i].to;
     70       if (v!=son[x]&&v!=fa)
     71     dfs2(v,v,x);
     72     }
     73   last[x]=cnt;
     74 }
     75 int LCA(int u,int v)
     76 {
     77   while (top[u]!=top[v])
     78     {
     79       if (dep[top[u]]<dep[top[v]]) swap(u,v);
     80       u=pa[top[u]];
     81     }
     82   if (dep[u]<dep[v]) return u;
     83   else return v;
     84 }
     85 int getson(int u,int v)
     86 {
     87   int last=0;
     88   while (top[v]!=top[u])
     89     {
     90       last=top[v];
     91       v=pa[last];
     92     }
     93   if (u==v) return last;
     94   return son[u];
     95 }
     96 void update(int x,int d1,int y,int d2)
     97 {
     98   while (x<=n)
     99     {
    100       c[x]+=d1;
    101       x+=(x&(-x));
    102     }
    103   y++;
    104   while (y<=n)
    105     {
    106       c[y]+=d2;
    107       y+=(y&(-y));
    108     }
    109 }
    110 int get_sum(int x)
    111 {
    112   int s=0;
    113   while (x)
    114     {
    115       s+=c[x];
    116       x-=x&(-x);
    117     }
    118   return s;
    119 }
    120 void solve(int l,int r,int st,int ed)
    121 {int i;
    122   if (st>ed) return;
    123   if (l==r)
    124     {
    125       for (i=st;i<=ed;i++)
    126     ans[query[i].id]=opt[l].k;
    127       return;
    128     }
    129   int mid=(l+r)/2;
    130   int siz=0;
    131   for (i=l;i<=mid;i++)
    132     {
    133       event[++siz]=(ALUGE){opt[i].x1,opt[i].y1,opt[i].y2,1,0};
    134       event[++siz]=(ALUGE){opt[i].x2,opt[i].y1,opt[i].y2,-1,n+1};
    135     }
    136   for (i=st;i<=ed;i++)
    137     {
    138       event[++siz]=(ALUGE){query[i].x,query[i].y,0,0,i};
    139     }
    140   sort(event+1,event+siz+1,cmpe);
    141   memset(c,0,sizeof(c));
    142   for (i=1;i<=siz;i++)
    143     {
    144       if (event[i].id<=ed&&event[i].id>=st) sum[event[i].id]=get_sum(event[i].y1);
    145       else update(event[i].y1,event[i].d,event[i].y2,-event[i].d);
    146     }
    147   int cnta=0,cntb=0;
    148   for (i=st;i<=ed;i++)
    149     {
    150       if (sum[i]>=query[i].k) qa[++cnta]=query[i];
    151       else qb[++cntb]=query[i],qb[cntb].k-=sum[i];
    152     }
    153   for (i=st;i<=st+cnta-1;i++)
    154     query[i]=qa[i-st+1];
    155   for (i=st+cnta;i<=ed;i++)
    156     query[i]=qb[i-st-cnta+1];
    157   solve(l,mid,st,st+cnta-1);
    158   solve(mid+1,r,st+cnta,ed);
    159 }
    160 int main()
    161 {
    162   int i,u,v,d;
    163   cin>>n>>p>>q;
    164   for (i=1;i<=n-1;i++)
    165     {
    166       scanf("%d%d",&u,&v);
    167       add(u,v);add(v,u);
    168     }
    169   dfs1(1,0);dfs2(1,1,0);
    170   for (i=1;i<=p;i++)
    171     {
    172       scanf("%d%d%d",&u,&v,&d);
    173       if (dfn[u]>dfn[v]) swap(u,v);
    174       int w=LCA(u,v);
    175       if (u==w)
    176     {
    177       w=getson(u,v);
    178       if (dfn[w]>1) opt[++cntp]=(FFF){1,dfn[w]-1,dfn[v],last[v],d};
    179       if (last[w]<n) opt[++cntp]=(FFF){dfn[v],last[v],last[w]+1,n,d};
    180     }
    181       else
    182     {
    183       opt[++cntp]=(FFF){dfn[u],last[u],dfn[v],last[v],d};
    184     }
    185     }
    186   p=cntp;
    187   for (i=1;i<=q;i++)
    188     {
    189       scanf("%d%d%d",&u,&v,&d);
    190       if (dfn[u]>dfn[v]) swap(u,v);
    191       query[i]=(ZYYS){dfn[u],dfn[v],d,i};
    192     }
    193   sort(opt+1,opt+p+1,cmpp);
    194   sort(query+1,query+q+1,cmpq);
    195   solve(1,p,1,q);
    196   for (i=1;i<=q;i++)
    197     printf("%d
    ",ans[i]);
    198 }
  • 相关阅读:
    第十五章:字段与属性
    第二十章:封装与继承
    第二十一章;泛型List
    第十九章:对象初始化器
    第十八章:构造方式
    第十七章:方法的重载
    request和response对象常用方法
    面向对象(1)
    request和response
    tomcat
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/8176196.html
Copyright © 2020-2023  润新知