BZOJ 4009: [HNOI2015]接水果 整体二分+DFS序+扫描线
以前一直以为这道题很恶心,事实证明还好,好多地方脑残写丑了.
code:
#include <cstdio> #include <string> #include <cstring> #include <algorithm> #define N 50003 using namespace std; void setIO(string s) { string in=s+".in"; string out=s+".out"; freopen(in.c_str(),"r",stdin); freopen(out.c_str(),"w",stdout); } namespace BIT { int C[N]; int lowbit(int t) { return t&(-t); } void update(int x,int v) { for(;x<N;x+=lowbit(x)) { C[x]+=v; } } int query(int x) { int tmp=0; for(;x>0;x-=lowbit(x)) { tmp+=C[x]; } return tmp; } void clr(int x) { for(;x<N;x+=lowbit(x)) { C[x]=0; } } }; int n,P,Q; int dfn; int edges; int hd[N],to[N<<1],nex[N<<1]; int fa[20][N]; int st[N],ed[N],dep[N]; int A[N]; int answer[N]; struct data { int x1; int y1; int x2; int y2; int val; data(int x1=0,int y1=0,int x2=0,int y2=0,int val=0):x1(x1),y1(y1),x2(x2),y2(y2),val(val){} }t[N],tmp1[N],tmp2[N]; struct qu { int x,y,id,kth; qu(int x=0,int y=0,int id=0,int kth=0):x(x),y(y),id(id),kth(kth){} }as[N],gl[N],gr[N]; struct Seg { int x,l,r,d; Seg(int x=0,int l=0,int r=0,int d=0):x(x),l(l),r(r),d(d){} }sg[N]; bool cmp_seg(Seg a,Seg b) { return a.x<b.x; } bool cmp_qu(qu a,qu b) { return a.x<b.x; } void add(int u,int v) { nex[++edges]=hd[u],hd[u]=edges,to[edges]=v; } void dfs(int u,int ff) { fa[0][u]=ff; for(int i=1;i<20;++i) { fa[i][u]=fa[i-1][fa[i-1][u]]; } st[u]=++dfn; dep[u]=dep[ff]+1; for(int i=hd[u];i;i=nex[i]) { int v=to[i]; if(v==ff) { continue; } dfs(v,u); } ed[u]=dfn; } int LCA(int x,int y) { int i,j; if(dep[x]!=dep[y]) { if(dep[x]>dep[y]) { swap(x,y); } for(i=19;i>=0;--i) { if(dep[fa[i][y]]>=dep[x]) { y=fa[i][y]; } } } if(x==y) { return x; } for(i=19;i>=0;--i) { if(fa[i][x]!=fa[i][y]) { x=fa[i][x]; y=fa[i][y]; } } return fa[0][x]; } int jump(int x,int d) { for(int i=19;i>=0;--i) { if(dep[fa[i][x]]>=d) { x=fa[i][x]; } } return x; } void solve(int l,int r,int l1,int r1,int L,int R) { if(l>r||l1>r1||L>R) { return; } if(l==r) { for(int i=L;i<=R;++i) { answer[as[i].id]=l; } return; } int s=0; int mid=(l+r)>>1; int cn1=0,cn2=0; int as1=0,as2=0; for(int i=l1;i<=r1;++i) { if(t[i].val<=mid) { tmp1[++cn1]=t[i]; // 是左面的 sg[++s]=Seg(t[i].x1,t[i].x2,t[i].y2,1); sg[++s]=Seg(t[i].y1+1,t[i].x2,t[i].y2,-1); } else { tmp2[++cn2]=t[i]; } } sort(sg+1,sg+1+s,cmp_seg); int j=1; for(int i=L;i<=R;++i) { while(j<=s&&sg[j].x<=as[i].x) { BIT::update(sg[j].l,sg[j].d); BIT::update(sg[j].r+1,sg[j].d*-1); ++j; } int tmp=BIT::query(as[i].y); if(tmp>=as[i].kth) { gl[++as1]=as[i]; } else { as[i].kth-=tmp; gr[++as2]=as[i]; } } for(int i=1;i<=s;++i) { BIT::clr(sg[i].l); BIT::clr(sg[i].r+1); } int pos=l1; for(int i=1;i<=cn1;++i) { t[pos++]=tmp1[i]; } for(int i=1;i<=cn2;++i) { t[pos++]=tmp2[i]; } pos=L; for(int i=1;i<=as1;++i) { as[pos++]=gl[i]; } for(int i=1;i<=as2;++i) { as[pos++]=gr[i]; } solve(l,mid,l1,l1+cn1-1,L,L+as1-1); solve(mid+1,r,l1+cn1,r1,L+as1,R); } int main() { // setIO("input"); int i,j,t1=0; scanf("%d%d%d",&n,&P,&Q); for(i=1;i<n;++i) { int x,y; scanf("%d%d",&x,&y); add(x,y); add(y,x); } dfs(1,0); for(i=1;i<=P;++i) { int u,v,c; scanf("%d%d%d",&u,&v,&c); A[i]=c; int lca=LCA(u,v); if(lca!=u&&lca!=v) { if(st[u]>st[v]) { swap(u,v); } t[++t1]=data(st[u],ed[u],st[v],ed[v],c); } else { if(lca==u) { swap(u,v); } int w=jump(u,dep[v]+1); if(st[w]-1>=1) { t[++t1]=data(1,st[w]-1,st[u],ed[u],c); } if(ed[w]+1<=n) { t[++t1]=data(st[u],ed[u],ed[w]+1,n,c); } } } sort(A+1,A+1+P); int cnt=unique(A+1,A+1+P)-A-1; for(i=1;i<=t1;++i) { t[i].val=lower_bound(A+1,A+1+cnt,t[i].val)-A; } for(i=1;i<=Q;++i) { int x,y,z; scanf("%d%d%d",&x,&y,&z); if(st[x]>st[y]) { swap(x,y); } as[i]=qu(st[x],st[y],i,z); } sort(as+1,as+1+Q,cmp_qu); solve(1,cnt,1,t1,1,Q); for(i=1;i<=Q;++i) { printf("%d\n",A[answer[i]]); } return 0; }