JZOJ 3360 BZOJ 3757 苹果树
分析
树上莫队解决此题
代码
#include <cstdio>
#include <cctype>
#include <cmath>
#include <algorithm>
#define rr register
using namespace std;
const int N=50011;
struct node{int y,next;}e[N<<1],E[N<<2]; bool v[N];
struct rec{int l,r,la,lb,lca,rk;}q[N<<1];
int ls[N],hs[N],dfn[N<<1],ofn[N],ifn[N],a[N],n,m,k,K,block,root,cnt[N<<1],now,ans[N<<1],pos[N<<1],tot,Lca[N<<2],f[N];
inline signed iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
inline void print(int ans){
if (ans>9) print(ans/10);
putchar(ans%10+48);
}
inline void Add(int x,int y){
e[++k]=(node){y,ls[x]},ls[x]=k,
e[++k]=(node){x,ls[y]},ls[y]=k;
}
inline void ADD(int x,int y){
E[++K]=(node){y,hs[x]},hs[x]=K,
E[++K]=(node){x,hs[y]},hs[y]=K;
}
inline signed getf(int u){return f[u]==u?u:f[u]=getf(f[u]);}
inline void dfs(int x){
f[x]=x,v[x]=0; dfn[ifn[x]=++tot]=x;
for (rr int i=ls[x];i;i=e[i].next) if (v[e[i].y])
dfs(e[i].y),f[e[i].y]=x; dfn[ofn[x]=++tot]=x;
for (rr int i=hs[x];i;i=E[i].next)
if (!v[E[i].y]) Lca[i]=Lca[i^1]=getf(E[i].y);
}
bool cmp(rec x,rec y){return (pos[x.l]^pos[y.l])?pos[x.l]<pos[y.l]:((pos[x.l]&1)?x.r<y.r:x.r>y.r);}
inline void add(int x){now+=++cnt[x]==1;}
inline void del(int x){now-=!(--cnt[x]);}
inline void update(int x){
if (!x) return; v[x=dfn[x]]^=1;
v[x]?add(a[x]):del(a[x]);
}
signed main(){
n=iut(); m=iut(); block=sqrt(n<<1); k=K=1;
for (rr int i=1;i<=n;++i) a[i]=iut(),v[i]=1;
for (rr int i=1;i<=n;++i){
rr int x=iut(),y=iut();
if (!x||!y) root=x+y; else Add(x,y);
}
for (rr int i=1;i<=m;++i)
q[i]=(rec){iut(),iut(),iut(),iut(),0,i},ADD(q[i].l,q[i].r);
dfs(root); for (rr int i=1;i<=tot;++i) pos[i]=i/block+1;
for (rr int i=1;i<=m;++i){
q[i].lca=Lca[i<<1];
if (q[i].lca==q[i].l||q[i].lca==q[i].r) q[i].lca=0;
if (ifn[q[i].l]>ifn[q[i].r]) q[i].l^=q[i].r,q[i].r^=q[i].l,q[i].l^=q[i].r;
ofn[q[i].r]<=ofn[q[i].l]?(q[i].l=ifn[q[i].l],q[i].r=ifn[q[i].r]):(q[i].l=ofn[q[i].l],q[i].r=ifn[q[i].r]);
}
sort(q+1,q+1+m,cmp);
for (rr int i=1,L=0,R=0;i<=m;++i){
for (;L<q[i].l;++L) update(L);
for (;L>q[i].l;--L) update(L-1);
for (;R>q[i].r;--R) update(R);
for (;R<q[i].r;++R) update(R+1);
if (q[i].lca) add(a[q[i].lca]);
(cnt[q[i].la]&&cnt[q[i].lb]&&q[i].la!=q[i].lb)?(ans[q[i].rk]=now-1):(ans[q[i].rk]=now);
if (q[i].lca) del(a[q[i].lca]);
}
for (rr int i=1;i<=m;++i) print(ans[i]),putchar(10);
return 0;
}
JZOJ 3362 数数(分块打表鬼才题)
–
JZOJ 3397 洛谷 4556 雨天的尾巴
分析
树上差分,线段树自底向上合并,然而洛谷95分不知所措
代码
#include <cstdio>
#include <cctype>
#define rr register
#define max(a,b) ((a)>(b)?(a):(b))
using namespace std;
const int p=136303,N=100011;
struct node{int y,next;}e[N<<1],E[N<<1]; int w[p<<5],lson[p<<5],rson[p<<5];
struct rec{int u,v,z,lca;}q[N]; bool v[N];
int k=1,K=1,ls[N],hs[N],hash[p+1],f[N],fat[N],dep[N],tot,Lca[N<<1],ans[N],n,m;
inline signed iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
inline void print(int ans){
if (ans>9) print(ans/10);
putchar(ans%10+48);
}
inline void add(int x,int y){
e[++k]=(node){y,ls[x]},ls[x]=k,
e[++k]=(node){x,ls[y]},ls[y]=k;
}
inline void Add(int x,int y){
E[++K]=(node){y,hs[x]},hs[x]=K,
E[++K]=(node){x,hs[y]},hs[y]=K;
}
inline signed locate(int x){
rr int now=x%p;
while (hash[now]&&hash[now]!=x) now=now%p+1;
hash[now]=x; return now;
}
inline signed getf(int u){return f[u]==u?u:f[u]=getf(f[u]);}
inline void init(int x){
f[x]=x,v[x]=0,dep[x]=dep[fat[x]]+1;
for (rr int i=ls[x];i;i=e[i].next) if (v[e[i].y])
fat[e[i].y]=x,init(e[i].y),f[e[i].y]=x;
for (rr int i=hs[x];i;i=E[i].next)
if (!v[E[i].y]) Lca[i]=Lca[i^1]=getf(E[i].y);
}
inline void update(int x,int l,int r,int pos,int y){
if (l==r) {w[x]+=y; return;}
rr int mid=(l+r)>>1;
if (pos<=mid){
if (!lson[x]) lson[x]=++tot;
update(lson[x],l,mid,pos,y);
}else{
if (!rson[x]) rson[x]=++tot;
update(rson[x],mid+1,r,pos,y);
}
w[x]=max(w[lson[x]],w[rson[x]]);
}
inline void merge(int x,int last,int l,int r){
if (l==r) {w[x]+=w[last]; return;}
rr int mid=(l+r)>>1;
if (lson[last]){
if (!lson[x]) lson[x]=lson[last];
else merge(lson[x],lson[last],l,mid);
}
if (rson[last]){
if (!rson[x]) rson[x]=rson[last];
else merge(rson[x],rson[last],mid+1,r);
}
w[x]=max(w[lson[x]],w[rson[x]]);
}
inline signed query(int x,int l,int r){
if (l==r) return l;
rr int mid=(l+r)>>1;
if (w[lson[x]]>=w[rson[x]]) return query(lson[x],l,mid);
else return query(rson[x],mid+1,r);
}
inline void dfs(int x){
v[x]=1;
for (rr int i=ls[x];i;i=e[i].next)
if (!v[e[i].y])
dfs(e[i].y),merge(x,e[i].y,1,p);
ans[x]=query(x,1,p);
}
signed main(){
n=iut(); m=iut(); v[n]=1;
for (rr int i=1;i<n;++i) add(iut(),iut()),v[i]=1;
for (rr int i=1;i<=m;++i) q[i]=(rec){iut(),iut(),locate(iut()),0},Add(q[i].u,q[i].v);
init(1); tot=n;
for (rr int i=1;i<=m;++i){
q[i].lca=Lca[i<<1]; if (dep[q[i].u]<dep[q[i].v]) q[i].u^=q[i].v,q[i].v^=q[i].u,q[i].u^=q[i].v;
update(q[i].u,1,p,q[i].z,1),update(fat[q[i].lca],1,p,q[i].z,-1);
if (q[i].lca==q[i].v) continue;
update(q[i].v,1,p,q[i].z,1),update(q[i].lca,1,p,q[i].z,-1);
}
dfs(1);
for (rr int i=1;i<=n;++i) print(hash[ans[i]]),putchar(10);
return 0;
}