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]接水果的主要内容,如果未能解决你的问题,请参考以下文章