[整体二分 || 树套树 || 点分治] BZOJ 4009 [HNOI2015]接水果

来源:互联网 发布:淘宝哪家情侣装好看 编辑:程序博客网 时间:2024/05/21 18:40

整体二分的做法题解很多:http://blog.csdn.net/thy_asdf/article/details/50363672


点分治么 还不会233


树套树么 ORZ



打的整体二分


#include<cstdio>#include<cstdlib>#include<algorithm>using namespace std;inline char nc(){static char buf[100000],*p1=buf,*p2=buf;if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }return *p1++;}inline void read(int &x){char c=nc(),b=1;for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;}const int N=100005;namespace TREE{#define V G[p].vstruct edge{int u,v,next;};edge G[N<<1];int head[N],inum;inline void add(int u,int v,int p){G[p].u=u; G[p].v=v; G[p].next=head[u]; head[u]=p;}int clk;int size[N],pre[N],last[N],fat[N][21],depth[N];inline void dfs(int u,int fa){size[u]=1; pre[u]=++clk; depth[u]=depth[fa]+1; fat[u][0]=fa;for (int k=1;k<=20;k++) fat[u][k]=fat[fat[u][k-1]][k-1]; for (int p=head[u];p;p=G[p].next)if (V!=fa)dfs(V,u),size[u]+=size[V];last[u]=pre[u]+size[u]-1;}inline int LCA(int u,int v){      if (depth[u]<depth[v]) swap(u,v);      for (int k=20;~k;k--)          if ((depth[u]-depth[v])&(1<<k))              u=fat[u][k];      if (u==v) return u;      for (int k=20;~k;k--)          if (fat[u][k]!=fat[v][k])              u=fat[u][k],v=fat[v][k];      return fat[u][0];  }inline int SecLCA(int x,int y){      for (int k=20;~k;k--)          if (depth[fat[x][k]]>depth[y])              x=fat[x][k];      return x;  }}int n,P,Q;int ans[N];struct Query{int x,y,k;int idx;}que[N],tmp[N];int qtot;struct Matrix{int x1,x2,y1,y2,key;bool operator < (const Matrix &B) const{return key<B.key;}}mat[N<<1];int mtot;namespace BIT{#define lowbit(x) ((x)&-(x))int c[N];inline void add(int x,int t){for (int i=x;i<=n;i+=lowbit(i))c[i]+=t;}inline void add(int l,int r,int t){add(l,t); add(r+1,-t);}inline int query(int x){int ret=0;for (int i=x;i;i-=lowbit(i))ret+=c[i];return ret;}}struct event{int x,y1,y2,r;event() { }event(int x,int y1,int y2,int r):x(x),y1(y1),y2(y2),r(r) { }bool operator < (const event &B) const{return x==B.x?(r>B.r):(x<B.x);}}eve[N<<2];int tot;int cnt[N<<2];inline void Solve(int l,int r,int ql,int qr){if (l==r){for (int i=ql;i<=qr;i++) ans[que[i].idx]=mat[l].key;return;}int mid=(l+r)>>1;tot=0;for (int i=l;i<=mid;i++) eve[++tot]=event(mat[i].x1,mat[i].y1,mat[i].y2,1),eve[++tot]=event(mat[i].x2,mat[i].y1,mat[i].y2,-1);for (int i=ql;i<=qr;i++) eve[++tot]=event(que[i].x,que[i].y,i,0);sort(eve+1,eve+tot+1);for (int i=1;i<=tot;i++)if (eve[i].r==1)BIT::add(eve[i].y1,eve[i].y2,1);else if (eve[i].r==-1)BIT::add(eve[i].y1,eve[i].y2,-1);else if (eve[i].r==0)cnt[eve[i].y2]=BIT::query(eve[i].y1);int L=ql-1,R=qr+1;for (int i=ql;i<=qr;i++)if (cnt[i]<que[i].k)tmp[--R]=que[i],tmp[R].k-=cnt[i];elsetmp[++L]=que[i];for (int i=ql;i<=qr;i++)que[i]=tmp[i];if (ql<=L) Solve(l,mid,ql,L);if (R<=qr) Solve(mid+1,r,R,qr);}int main(){using namespace TREE;int iu,iv,ik,w,lca;freopen("t.in","r",stdin);freopen("t.out","w",stdout);read(n); read(P); read(Q);for (int i=1;i<n;i++)read(iu),read(iv),add(iu,iv,++inum),add(iv,iu,++inum);dfs(1,0);for (int i=1;i<=P;i++){read(iu); read(iv); read(ik);if (pre[iu]>pre[iv]) swap(iu,iv);if ((lca=LCA(iu,iv))==iu){w=SecLCA(iv,iu);if (pre[w]-1>0){mat[++mtot].key=ik;mat[mtot].x1=1; mat[mtot].x2=pre[w]-1; mat[mtot].y1=pre[iv]; mat[mtot].y2=last[iv];}if (last[w]+1<=n){mat[++mtot].key=ik;mat[mtot].x1=pre[iv]; mat[mtot].x2=last[iv]; mat[mtot].y1=last[w]+1; mat[mtot].y2=n; }}else{mat[++mtot].key=ik;mat[mtot].x1=pre[iu]; mat[mtot].x2=last[iu]; mat[mtot].y1=pre[iv]; mat[mtot].y2=last[iv];}}sort(mat+1,mat+mtot+1);for (int i=1;i<=Q;i++){read(iu); read(iv); read(ik);if (pre[iu]>pre[iv]) swap(iu,iv);que[++qtot].k=ik; que[qtot].x=pre[iu]; que[qtot].y=pre[iv]; que[qtot].idx=i;}Solve(1,mtot,1,qtot);for (int i=1;i<=Q;i++) printf("%d\n",ans[i]);return 0;}

0 0