zoukankan      html  css  js  c++  java
  • 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;
    }
    

      

  • 相关阅读:
    Windows API 的数据类型与 Delphi 数据类型对照表
    Delphi 编译错误信息表
    Delphi中的容器类
    Delphi 快捷键
    代码折叠
    [转]Delphi中record的使用
    [转]常用公共函数单元
    Delphi 运行时错误信息表
    C#调用Win32 的API函数User32.dll
    [转]Delphi程序启动参数的读取
  • 原文地址:https://www.cnblogs.com/clrs97/p/4792787.html
Copyright © 2011-2022 走看看