[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 小一定存在。
输出格式:
对于每个果子,输出一行表示选择的盘子的权值。
输入输出样例
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
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\n",ans[i]); 198 }