BZOJ4009 : [HNOI2015]接水果

对于一条路径x-y:

·若x与y成祖先-孩子关系,假设y是x的祖先,z是y到x方向的第一个节点,则包含它的路径满足:起点在x的子树里,且终点不在z的子树里。

·若x与y不成祖先-孩子关系,则包含它的路径满足:起点在x的子树里,且终点在y的子树里。

于是每个盘子可以拆成一个或两个矩形,每个水果可以当成两个点。

整体二分的时候扫描线+树状数组维护,时间复杂度$O(nlog^2n)$。

#include<cstdio>
#include<algorithm>
#define N 40010
using namespace std;
int n,m,Q,i,x,y,z,q[N],tmp[N],now[N],ans[N],T,pos[N],bit[N];
int g[N],nxt[N<<1],v[N<<1],ed,d[N],size[N],son[N],top[N],f[N],st[N],en[N],dfn;
struct E{
  int x1,x2,l1,r1,l2,r2,z;
  E(){}
  E(int _x1,int _x2,int _l1,int _r1,int _l2,int _r2,int _z){
    x1=_x1,x2=_x2,l1=_l1,r1=_r1,l2=_l2,r2=_r2,z=_z;
  }
}e[N];
inline bool cmp(const E&a,const E&b){return a.z<b.z;}
struct P{int x,y,k,p;P(){}P(int _x,int _y,int _k,int _p){x=_x,y=_y,k=_k,p=_p;}}a[N];
struct B{int x,l,r,t;B(){}B(int _x,int _l,int _r,int _t){x=_x,l=_l,r=_r,t=_t;}}b[N<<1];
inline bool cmpb(const B&a,const B&b){return a.x<b.x;}
struct C{int x,y,p;C(){}C(int _x,int _y,int _p){x=_x,y=_y,p=_p;}}c[N<<1];
inline bool cmpc(const C&a,const C&b){return a.x<b.x;}
inline void addedge(int x,int y){v[++ed]=y;nxt[ed]=g[x];g[x]=ed;}
void dfs(int x){
  size[x]=1;
  for(int i=g[x];i;i=nxt[i])if(v[i]!=f[x]){
    d[v[i]]=d[f[v[i]]=x]+1;dfs(v[i]);size[x]+=size[v[i]];
    if(size[v[i]]>size[son[x]])son[x]=v[i];
  }
}
void dfs2(int x,int y){
  st[x]=++dfn;top[x]=y;
  if(son[x])dfs2(son[x],y);
  for(int i=g[x];i;i=nxt[i])if(v[i]!=son[x]&&v[i]!=f[x])dfs2(v[i],v[i]);
  en[x]=dfn;
}
inline int lca2(int x,int y){
  int t;
  while(top[x]!=top[y])t=top[y],y=f[top[y]];
  return x==y?t:son[x];
}
inline void add(int x,int p){for(;x<=n;x+=x&-x)if(pos[x]<T)pos[x]=T,bit[x]=p;else bit[x]+=p;}
inline int ask(int x){int t=0;for(;x;x-=x&-x)if(pos[x]==T)t+=bit[x];return t;}
void solve(int l,int r,int h,int t){
  if(h>t)return;
  if(l==r){
    for(int i=h;i<=t;i++)ans[a[q[i]].p]=e[l].z;
    return;
  }
  int mid=(l+r)>>1,cb=0,cc=0;
  for(int i=l;i<=mid;i++){
    if(e[i].l1<=e[i].r1){
      b[cb++]=B(e[i].x1,e[i].l1,e[i].r1,1);
      b[cb++]=B(e[i].x2+1,e[i].l1,e[i].r1,-1);
    }
    if(e[i].l2<=e[i].r2){
      b[cb++]=B(e[i].x1,e[i].l2,e[i].r2,1);
      b[cb++]=B(e[i].x2+1,e[i].l2,e[i].r2,-1);
    }
  }
  for(int i=h;i<=t;i++){
    c[cc++]=C(a[q[i]].x,a[q[i]].y,i);
    c[cc++]=C(a[q[i]].y,a[q[i]].x,i);
    now[i]=0;
  }
  T++,sort(b,b+cb,cmpb),sort(c,c+cc,cmpc);
  for(int i=0,j=0;i<cc;i++){
    while(j<cb&&b[j].x<=c[i].x)add(b[j].l,b[j].t),add(b[j].r+1,-b[j].t),j++;
    now[c[i].p]+=ask(c[i].y);
  }
  int L=h,R=t;
  for(int i=h;i<=t;i++)if(now[i]>=a[q[i]].k)tmp[L++]=q[i];else a[q[i]].k-=now[i],tmp[R--]=q[i];
  for(int i=h;i<=t;i++)q[i]=tmp[i];
  solve(l,mid,h,R),solve(mid+1,r,R+1,t);
}
inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
int main(){
  read(n),read(m),read(Q);
  for(i=1;i<n;i++)read(x),read(y),addedge(x,y),addedge(y,x);
  dfs(1),dfs2(1,1);
  for(i=1;i<=m;i++){
    read(x),read(y),read(z);
    if(d[x]<d[y])swap(x,y);
    if(st[y]<=st[x]&&en[x]<=en[y])y=lca2(y,x),e[i]=E(st[x],en[x],1,st[y]-1,en[y]+1,n,z);
    else e[i]=E(st[x],en[x],st[y],en[y],1,0,z);
  }
  sort(e+1,e+m+1,cmp);
  for(i=1;i<=Q;i++){
    q[i]=i;
    read(x),read(y),read(z);
    a[i]=P(st[x],st[y],z,i);
  }
  solve(1,m,1,Q);
  for(i=1;i<=Q;i++)printf("%d
",ans[i]);
  return 0;
}

  

原文地址:https://www.cnblogs.com/clrs97/p/4792787.html