BZOJ4154:[IPSC2015]Generating Synergy
阿新 • • 發佈:2019-02-17
include string con mem html space main int names
淺談\(K-D\) \(Tree\):https://www.cnblogs.com/AKMer/p/10387266.html
題目傳送門:https://lydsy.com/JudgeOnline/problem.php?id=4154
每個節點看做是點\((dfn_i,dep_i)\),然後對於距離\(a\)的不超過\(l\)的在\(a\)子樹中的點就是正方形\([dfn_a,dfn_a+siz_a-1][dep_a,dep_a+l]\),直接範圍\(cover\)和單點查詢即可。
時間復雜度:\(O(n\sqrt{n})\)
空間復雜度:\(O(n)\)
代碼如下:
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn=1e5+5,inf=2e9,mo=1e9+7; int n,m,c,tot,cnt,pps,ans,Case; int now[maxn],pre[maxn<<1],son[maxn<<1]; int dfn[maxn],node[maxn],siz[maxn],dep[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 u,int D) { dfn[u]=++cnt,dep[u]=D,siz[u]=1; for(int p=now[u],v=son[p];p;p=pre[p],v=son[p]) dfs(v,D+1),siz[u]+=siz[v]; } struct kd_tree { int root,top; int stk[maxn],fa[maxn]; struct point { int cov,col,ls,rs; int c[2],mn[2],mx[2]; point() {} point(int _x,int _y) { mn[0]=mx[0]=c[0]=_x; mn[1]=mx[1]=c[1]=_y; col=1,cov=-1,ls=rs=0; } bool operator<(const point &a)const { return c[pps]<a.c[pps]; } }p[maxn]; int build(int l,int r,int d) { int mid=(l+r)>>1,u=mid;pps=d; nth_element(p+l,p+mid,p+r+1); node[p[u].c[0]]=u; if(l<mid)p[u].ls=build(l,mid-1,d^1); if(r>mid)p[u].rs=build(mid+1,r,d^1); int ls=p[u].ls,rs=p[u].rs;fa[ls]=fa[rs]=u; for(int i=0;i<2;i++) { int mn=min(p[ls].mn[i],p[rs].mn[i]); p[u].mn[i]=min(p[u].mn[i],mn); int mx=max(p[ls].mx[i],p[rs].mx[i]); p[u].mx[i]=max(p[u].mx[i],mx); } return u; } void prepare() { p[0].mn[0]=p[0].mn[1]=inf; p[0].mx[0]=p[0].mx[1]=-inf; for(int i=1;i<=n;i++) p[i]=point(dfn[i],dep[i]); root=build(1,n,0); } void make_tag(int u,int c) { p[u].col=p[u].cov=c; } void push_down(int u) { if(p[u].cov==-1)return; if(p[u].ls)make_tag(p[u].ls,p[u].cov); if(p[u].rs)make_tag(p[u].rs,p[u].cov); p[u].cov=-1; } void query(int u,int id) { int tmp=u; while(fa[u])stk[++top]=fa[u],u=fa[u]; while(top)push_down(stk[top--]); ans=(ans+1ll*id*p[tmp].col%mo)%mo; } void change(int u,int x1,int x2,int y1,int y2,int color) { if(x2<p[u].mn[0]||x1>p[u].mx[0])return; if(y2<p[u].mn[1]||y1>p[u].mx[1])return; bool bo1=(x1<=p[u].mn[0]&&p[u].mx[0]<=x2); bool bo2=(y1<=p[u].mn[1]&&p[u].mx[1]<=y2); if(bo1&&bo2) {make_tag(u,color);return;} push_down(u); bo1=(x1<=p[u].c[0]&&p[u].c[0]<=x2); bo2=(y1<=p[u].c[1]&&p[u].c[1]<=y2); if(bo1&&bo2)p[u].col=color; if(p[u].ls)change(p[u].ls,x1,x2,y1,y2,color); if(p[u].rs)change(p[u].rs,x1,x2,y1,y2,color); } }T; void clear() { ans=tot=cnt=pps=0; memset(now,0,sizeof(now)); memset(T.fa,0,sizeof(T.fa)); } int main() { Case=read(); while(Case--) { n=read(),c=read(),m=read(),clear(); for(int i=2,x;i<=n;i++) x=read(),add(x,i); dfs(1,1);T.prepare(); for(int i=1;i<=m;i++) { int a=read(),l=read(),opt=read(); if(!opt)T.query(node[dfn[a]],i); else T.change(T.root,dfn[a],dfn[a]+siz[a]-1,dep[a],dep[a]+l,opt); } printf("%d\n",ans); } return 0; }
BZOJ4154:[IPSC2015]Generating Synergy