BZOJ4009:[HNOI2015]接水果(整體二分版)
阿新 • • 發佈:2019-02-25
整體 二維 .cn names etc space for char fine
淺談離線分治算法:https://www.cnblogs.com/AKMer/p/10415556.html
題目傳送門:https://lydsy.com/JudgeOnline/problem.php?id=4009
樹套樹寫法:https://www.cnblogs.com/AKMer/p/10181501.html
把二維線段樹部分改成整體二分就行了。
時間復雜度:\(O(nlog^2n)\)
空間復雜度:\(O(n)\)
代碼如下:
#include <cstdio> #include <algorithm> using namespace std; #define low(i) ((i)&(-(i))) const int maxn=4e4+5; bool bo[maxn*5]; int n,P,Q,tot,cnt,sum;int f[maxn][17]; int now[maxn],pre[maxn<<1],son[maxn<<1]; int dep[maxn],siz[maxn],dfn[maxn],ans[maxn]; int read() { int x=0,f=1;char ch=getchar(); for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1; for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0'; return x*f; } void add(int a,int b) { pre[++tot]=now[a]; now[a]=tot,son[tot]=b; } void dfs(int fa,int u) { siz[u]=1,dfn[u]=++cnt; f[u][0]=fa,dep[u]=dep[fa]+1; for(int i=1;i<17;i++) f[u][i]=f[f[u][i-1]][i-1]; for(int p=now[u],v=son[p];p;p=pre[p],v=son[p]) if(v!=fa)dfs(u,v),siz[u]+=siz[v]; } struct Oper { int opt,x,y1,y2,k; Oper() {} Oper(int _opt,int _x,int _y1,int _y2,int _k) { opt=_opt,x=_x,y1=_y1,y2=_y2,k=_k; } bool operator<(const Oper &a)const { if(x==a.x)return (opt!=0)>(a.opt!=0); return x<a.x; } }p[maxn*5],tmp[maxn*5]; struct tree_array { int c[maxn]; void add(int pos,int v) { for(int i=pos;i<=n;i+=low(i)) c[i]+=v; } int query(int pos) { int res=0; for(int i=pos;i;i-=low(i)) res+=c[i]; return res; } }T; void solve(int l,int r,int st,int ed) { if(ed<st)return; if(l==r) { for(int i=st;i<=ed;i++) if(!p[i].opt)ans[p[i].y2]=l; return; } int mid=(l+r)>>1,num=0; for(int i=st;i<=ed;i++) if(p[i].opt) { if(p[i].k<=mid) { bo[i]=1,num++; T.add(p[i].y1,p[i].opt); T.add(p[i].y2+1,-p[i].opt); } else bo[i]=0; } else { int res=T.query(p[i].y1); if(res>=p[i].k)bo[i]=1,num++; else bo[i]=0,p[i].k-=res; } for(int i=st;i<=ed;i++) if(p[i].opt&&p[i].k<=mid) { T.add(p[i].y1,-p[i].opt); T.add(p[i].y2+1,p[i].opt); } int ED=st,ST=st+num; for(int i=st;i<=ed;i++) if(bo[i])tmp[ED++]=p[i]; else tmp[ST++]=p[i]; for(int i=st;i<=ed;i++) p[i]=tmp[i]; solve(l,mid,st,ED-1),solve(mid+1,r,ED,ed); } int main() { n=read(),P=read(),Q=read(); for(int i=1;i<n;i++) { int x=read(),y=read(); add(x,y),add(y,x); } dfs(0,1); for(int i=1;i<=P;i++) { int u=read(),v=read(),c=read(); if(dfn[u]>dfn[v])swap(u,v); if(dfn[u]+siz[u]-1>=dfn[v]+siz[v]-1) { int pos=v; for(int i=16;~i;i--) if(dep[f[pos][i]]>dep[u]) pos=f[pos][i]; p[++sum]=Oper(1,1,dfn[v],dfn[v]+siz[v]-1,c); p[++sum]=Oper(-1,dfn[pos],dfn[v],dfn[v]+siz[v]-1,c); p[++sum]=Oper(1,dfn[v],dfn[pos]+siz[pos],n,c); p[++sum]=Oper(-1,dfn[v]+siz[v],dfn[pos]+siz[pos],n,c); } else { p[++sum]=Oper(1,dfn[u],dfn[v],dfn[v]+siz[v]-1,c); p[++sum]=Oper(-1,dfn[u]+siz[u],dfn[v],dfn[v]+siz[v]-1,c); } } for(int i=1;i<=Q;i++) { int u=read(),v=read(),k=read(); if(dfn[u]>dfn[v])swap(u,v); p[++sum]=Oper(0,dfn[u],dfn[v],i,k); } sort(p+1,p+sum+1); solve(1,1e9,1,sum); for(int i=1;i<=Q;i++) printf("%d\n",ans[i]); return 0; }
BZOJ4009:[HNOI2015]接水果(整體二分版)