记录编号 446053 评测结果 AAAAAAAAAA
题目名称 [HNOI 2015]接水果 最终得分 100
用户昵称 Gravatartest 是否通过 通过
代码语言 C++ 运行时间 1.138 s
提交时间 2017-09-07 15:26:24 内存使用 8.86 MiB
显示代码纯文本
#include    <iostream>
#include    <cstdio>
#include    <cstdlib>
#include    <algorithm>
#include    <vector>
#include    <cstring>
#include    <queue>
#include    <complex>
#include    <stack>
#define LL long long int
#define dob double
using namespace std;

const int N = 40010;
struct Node{int to,next;}E[N<<1];
struct Plate{
  int xl,xr,yl,yr,val;
  bool operator <(const Plate &p)const{
    return val<p.val;
  }
}plate[N];
struct Fruit{
  int x,y,k,id;
  bool operator <(const Fruit &f)const{
    return x<f.x;
  }
}fruit[N],que1[N],que2[N];
struct Data{
  int x,l,r,val;
  bool operator <(const Data &l)const{
    return x<l.x;
  }
}Line[N<<1];
int n,P,Q,Ans[N],cnt,head[N],tot;
int fa[17][N],dep[N],size[N],son[N],top[N],dfn[N],tim,last[N];
struct Bit{
  int A[N],vis[N];
  inline int lb(int x){
    return x&-x;
  }
  inline void upd(int x,int val){
    for(;x<=n;x+=lb(x)){
      if(vis[x]!=tim)A[x]=0,vis[x]=tim;
      A[x]+=val;
    }
  }
  inline void update(int l,int r,int val){
    upd(l,val);upd(r+1,-val);
  }
  inline int query(int x,int ans=0){
    for(;x;x-=lb(x)){
      if(vis[x]!=tim)A[x]=0,vis[x]=tim;
      ans+=A[x];
    }
    return ans;
  }
}T;

inline int gi(){
  int x=0,res=1;char ch=getchar();
  while(ch>'9'||ch<'0'){if(ch=='-')res*=-1;ch=getchar();}
  while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
  return x*res;
}

inline void link(int u,int v){
  E[++tot]=(Node){v,head[u]};
  head[u]=tot;
}

inline void join(int x){
  for(int i=1;i<=16;++i)
    fa[i][x]=fa[i-1][fa[i-1][x]];
}

inline void dfs1(int x,int fat){
  fa[0][x]=fat;dep[x]=dep[fat]+1;size[x]=1;join(x);
  for(int e=head[x];e;e=E[e].next){
    int y=E[e].to;if(y==fa[0][x])continue;
    dfs1(y,x);size[x]+=size[y];
    if(size[son[x]]<size[y])son[x]=y;
  }
}

inline void dfs2(int x,int tp){
  top[x]=tp;dfn[x]=++tim;
  if(son[x])dfs2(son[x],tp);
  for(int e=head[x];e;e=E[e].next){
    int y=E[e].to;
    if(y==fa[0][x] || y==son[x])continue;
    dfs2(y,y);
  }
  last[x]=tim;
}

inline int lca(int x,int y){
  while(top[x] != top[y]){
    if(dep[top[x]]<dep[top[y]])swap(x,y);
    x=fa[0][top[x]];
  }
  return dep[x]<dep[y]?x:y;
}

inline int jump(int x,int goal){
  //printf("jump %d %d\n",x,goal);
  for(int i=16;i>=0;--i)
    if(dep[fa[i][x]]>dep[goal])
      x=fa[i][x];
  return x;
}

/*
  把答案(盘子)二分。
  把左边的矩形加进去。
  然后check,calc一下盘子个数。
  递归处理。
*/

inline void solve(int optl,int optr,int l,int r){
  if(optl>optr || l>r)return;++tim;
  if(optl==optr){
    for(int i=l;i<=r;++i)
      Ans[fruit[i].id]=plate[optl].val;
    return;
  }
  int mid=(optl+optr)>>1,tot1=0,tot2=0,k=l,tmp=0,cnt1=1,cnt2=l;
  for(int i=optl;i<=mid;++i){
    Line[++tmp]=(Data){plate[i].xl,plate[i].yl,plate[i].yr,1};
    Line[++tmp]=(Data){plate[i].xr+1,plate[i].yl,plate[i].yr,-1};
  }
  sort(Line+1,Line+tmp+1);sort(fruit+l,fruit+r+1);
  while(cnt1<=tmp && cnt2<=r){
    if(Line[cnt1].x<=fruit[cnt2].x){
      int xl=Line[cnt1].l,xr=Line[cnt1].r,val=Line[cnt1].val;
      T.update(xl,xr,val);cnt1++;
    }
    else{
      int sum=T.query(fruit[cnt2].y);
      if(sum>=fruit[cnt2].k)que1[++tot1]=fruit[cnt2++];
      else fruit[cnt2].k-=sum,que2[++tot2]=fruit[cnt2++];
    }
  }
  while(cnt2<=r){
    int sum=T.query(fruit[cnt2].y);
    if(sum>=fruit[cnt2].k)que1[++tot1]=fruit[cnt2++];
    else fruit[cnt2].k-=sum,que2[++tot2]=fruit[cnt2++];
  }
  for(int i=1;i<=tot1;++i)fruit[k++]=que1[i];
  for(int i=1;i<=tot2;++i)fruit[k++]=que2[i];
  solve(optl,mid,l,l+tot1-1);
  solve(mid+1,optr,l+tot1,r);
}

int main()
{
  freopen("fruit_hnoi2015.in","r",stdin);
  freopen("fruit_hnoi2015.out","w",stdout);
  n=gi();P=gi();Q=gi();
  for(int i=1;i<n;++i){
    int u=gi(),v=gi();
    link(u,v);link(v,u);
  }
  dfs1(1,1);dfs2(1,1);
  for(int i=1;i<=P;++i){
    int a=gi(),b=gi(),c=gi(),u=lca(a,b);
    if(dfn[a]>dfn[b])swap(a,b);
    if(u^a)plate[++cnt]=(Plate){dfn[a],last[a],dfn[b],last[b],c};
    else{
      int v=jump(b,a);
      if(dfn[v]>1)plate[++cnt]=(Plate){1,dfn[v]-1,dfn[b],last[b],c};
      if(last[v]<n)plate[++cnt]=(Plate){dfn[b],last[b],last[v]+1,n,c};
    }
  }
  sort(plate+1,plate+cnt+1);
  for(int i=1;i<=Q;++i){
    int a=gi(),b=gi(),k=gi();
    if(dfn[a]>dfn[b])swap(a,b);
    fruit[i]=(Fruit){dfn[a],dfn[b],k,i};
  }
  sort(fruit+1,fruit+Q+1);
  solve(1,cnt,1,Q);
  for(int i=1;i<=Q;++i)
    printf("%d\n",Ans[i]);
  
  /*fclose(stdin);
    fclose(stdout);*/
  return 0;
}