bzoj4009 [HNOI2015]接水果

Posted wfj_2048

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 小的那个盘子,每个盘子可重复使用(没有使用次数的上限:一个盘子接完一个水果后,后面还可继续接其他水果,只要它是水果路径的子路径)。幽香认为这个游戏很难,你能轻松解决给她看吗?

技术分享


正解:扫描线+整体二分。

这题竟然是权限题,真的操蛋。。给个链接算了,不想写题解了。。

http://blog.csdn.net/thy_asdf/article/details/50363672

话说我用树链剖分+树状数组这些小常数法宝都跑了0.4s是什么鬼。。

 

  1 //It is made by wfj_2048~
  2 #include <algorithm>
  3 #include <iostream>
  4 #include <complex>
  5 #include <cstring>
  6 #include <cstdlib>
  7 #include <cstdio>
  8 #include <vector>
  9 #include <cmath>
 10 #include <queue>
 11 #include <stack>
 12 #include <map>
 13 #include <set>
 14 #define inf (1<<30)
 15 #define N (100010)
 16 #define il inline
 17 #define RG register
 18 #define ll long long
 19 #define lb(x) (x & -x)
 20 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
 21 
 22 using namespace std;
 23 
 24 struct plate{ int x1,x2,y1,y2,v; }p[2*N];
 25 struct fruit{ int x,y,k,id; }q[N],qu1[N],qu2[N];
 26 struct node{ int x,y,v; }rhl[N];
 27 struct edge{ int nt,to; }g[2*N];
 28 
 29 int head[N],top[N],fa[N],son[N],dep[N],pos[N],dfn[N],ed[N],sz[N],c[N],ans[N],n,P,Q,num,cnt,tot;
 30 
 31 il int gi(){
 32     RG int x=0,q=1; RG char ch=getchar(); while ((ch<0 || ch>9) && ch!=-) ch=getchar();
 33     if (ch==-) q=-1,ch=getchar(); while (ch>=0 && ch<=9) x=x*10+ch-48,ch=getchar(); return q*x;
 34 }
 35 
 36 il int cmpp(RG plate a,RG plate b){ return a.v<b.v; }
 37 
 38 il int cmpq(RG fruit a,RG fruit b){ return a.x<b.x; }
 39 
 40 il int cmpx(RG node a,RG node b){ return a.x<b.x; }
 41 
 42 il void add(RG int x,RG int v){ for (;x<=n;x+=lb(x)) c[x]+=v; return; }
 43 
 44 il int query(RG int x){ RG int res=0; for (;x;x-=lb(x)) res+=c[x]; return res; }
 45 
 46 il void insert(RG int from,RG int to){ g[++num]=(edge){head[from],to},head[from]=num; return; }
 47 
 48 il void dfs1(RG int x,RG int p){
 49     fa[x]=p,dep[x]=dep[p]+1,sz[x]=1; RG int v;
 50     for (RG int i=head[x];i;i=g[i].nt){
 51     v=g[i].to; if (v==p) continue;
 52     dfs1(v,x); sz[x]+=sz[v];
 53     if (sz[son[x]]<=sz[v]) son[x]=v;
 54     }
 55     return;
 56 }
 57 
 58 il void dfs2(RG int x,RG int p,RG int anc){
 59     top[x]=anc,dfn[x]=++cnt,pos[cnt]=x;
 60     if (son[x]) dfs2(son[x],x,anc); RG int v;
 61     for (RG int i=head[x];i;i=g[i].nt){
 62     v=g[i].to; if (v==p || v==son[x]) continue;
 63     dfs2(v,x,v);
 64     }
 65     ed[x]=cnt; return;
 66 }
 67 
 68 il int jump(RG int u,RG int v){
 69     RG int la=0;
 70     while (top[u]!=top[v]){
 71     if (dep[top[u]]<dep[top[v]]) swap(u,v);
 72     la=top[u],u=fa[top[u]];
 73     }
 74     if (dep[u]>dep[v]) swap(u,v);
 75     return u==v ? la : pos[dfn[u]+1];
 76 }
 77 
 78 il int lca(RG int u,RG int v){
 79     while (top[u]!=top[v]){
 80     if (dep[top[u]]<dep[top[v]]) swap(u,v);
 81     u=fa[top[u]];
 82     }
 83     return dep[u]<dep[v] ? u : v;
 84 }
 85 
 86 il void solve(RG int l,RG int r,RG int L,RG int R){
 87     if (L>R) return;
 88     if (l==r){
 89     for (RG int i=L;i<=R;++i) ans[q[i].id]=p[l].v;
 90     return;
 91     }
 92     RG int mid=(l+r)>>1,cnt=0,pos=0,tmp=0,t1=0,t2=0;
 93     for (RG int i=l;i<=mid;++i){
 94     rhl[++cnt]=(node){p[i].x1,p[i].y1,1};
 95     rhl[++cnt]=(node){p[i].x1,p[i].y2+1,-1};
 96     rhl[++cnt]=(node){p[i].x2+1,p[i].y1,-1};
 97     rhl[++cnt]=(node){p[i].x2+1,p[i].y2+1,1};
 98     }
 99     sort(rhl+1,rhl+cnt+1,cmpx);
100     for (RG int i=L;i<=R;++i){
101     while (pos<cnt && rhl[pos+1].x<=q[i].x) pos++,add(rhl[pos].y,rhl[pos].v);
102     tmp=query(q[i].y); if (q[i].k<=tmp) qu1[++t1]=q[i]; else q[i].k-=tmp,qu2[++t2]=q[i];
103     }
104     while (pos<cnt) pos++,add(rhl[pos].y,rhl[pos].v);
105     for (RG int i=L,j=1;i<=L+t1-1;++i,++j) q[i]=qu1[j];
106     for (RG int i=L+t1,j=1;i<=R;++i,++j) q[i]=qu2[j];
107     solve(l,mid,L,L+t1-1),solve(mid+1,r,L+t1,R); return;
108 }
109 
110 il void work(){
111     n=gi(),P=gi(),Q=gi(); RG int u,v,k;
112     for (RG int i=1;i<n;++i) u=gi(),v=gi(),insert(u,v),insert(v,u);
113     dfs1(1,0),dfs2(1,0,1);
114     for (RG int i=1;i<=P;++i){
115     u=gi(),v=gi(),k=gi();
116     if (dfn[u]>dfn[v]) swap(u,v); RG int Lca=lca(u,v);
117     if (Lca!=u) p[++tot]=(plate){dfn[u],ed[u],dfn[v],ed[v],k};
118     else{
119         RG int w=jump(u,v);
120         if (dfn[w]>1) p[++tot]=(plate){1,dfn[w]-1,dfn[v],ed[v],k};
121         if (ed[w]<n) p[++tot]=(plate){dfn[v],ed[v],ed[w]+1,n,k};
122     }
123     }
124     for (RG int i=1;i<=Q;++i){
125     u=gi(),v=gi(),k=gi(); if (dfn[u]>dfn[v]) swap(u,v);
126     q[i]=(fruit){dfn[u],dfn[v],k,i};
127     }
128     sort(p+1,p+tot+1,cmpp),sort(q+1,q+Q+1,cmpq),solve(1,tot,1,Q);
129     for (RG int i=1;i<=Q;++i) printf("%d\n",ans[i]); return;
130 }
131 
132 int main(){
133     File("fruit");
134     work();
135     return 0;
136 }

 



以上是关于bzoj4009 [HNOI2015]接水果的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ4009 HNOI2015 接水果

BZOJ4009 [HNOI2015]接水果

bzoj4009 [HNOI2015]接水果

BZOJ4009 [HNOI2015] 接水果

BZOJ4009[HNOI2015]接水果 DFS序+整体二分+扫描线+树状数组

BZOJ4009 & 洛谷3242 & LOJ2113:[HNOI2015]接水果——题解