BS4150【NOI2014模拟17】花园

BS4150【NOI2014模拟17】花园(树剖,线段树,差分)

这道题可以差分然后线段树询问来做,同时也可以直接树剖然后在线段树内部用 set 维护。

可知线段树树高严格 \(logn\) ,所以单次修改是 \(O(log^3n)\) ,查询是 \(O(log^2n)\) ,1e5的数据比较卡,可以用差分的思路变成 2log 。

代码:

#include<bits/stdc++.h>
using namespace std;
template <typename T>
inline void read(T &x){
	x=0;char ch=getchar();bool f=false;
	while(!isdigit(ch))	f|=ch=='-',ch=getchar();
	while(isdigit(ch))	x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
	x=f?-x:x;
}
template <typename T>
inline void write(T x){
	if(x<0)	putchar('-'),x=-x;
	if(x>9)	write(x/10);
	putchar(x%10^48);
}
const int N=1e6+5;
#define ll long long 
int n,m,root;
int head[N],nex[N],to[N],idx,val[N];
int dep[N],siz[N],son[N],fa[N],dfn[N],top[N],rev[N],tot;
multiset<int>S[N<<2];
void Add(int u,int v){
	nex[++idx]=head[u];
	to[idx]=v;
	head[u]=idx;
	return ;
}
void Dfs1(int x,int f){
	siz[x]=1,fa[x]=f,dep[x]=dep[f]+1;
	for(int i=head[x];i;i=nex[i]){
		int y=to[i];
		if(y==f) continue;
		Dfs1(y,x);
		siz[x]+=siz[y];
		if(siz[y]>siz[son[x]]) son[x]=y;
	}
	return ;
}
void Dfs2(int x){
	if(x==son[fa[x]]) top[x]=top[fa[x]];
	else top[x]=x;
	dfn[x]=++tot;rev[tot]=x;
	if(son[x]) Dfs2(son[x]);
	for(int i=head[x];i;i=nex[i]){
		int y=to[i];
		if(y==fa[x]||y==son[x]) continue;
		Dfs2(y);
	}
	return ;
}
int sum[N<<2];
void Pushup(int x){
	multiset<int>::iterator it;
	for(it=S[x<<1].begin();it!=S[x<<1].end();it++) S[x].insert(*it);
	for(it=S[x<<1|1].begin();it!=S[x<<1|1].end();it++) S[x].insert(*it);
	sum[x]=S[x].size();
	return ;
}
void Update(int x,int lose,int get){
	if(lose==get) return ;
	while(floor(x>>1)>0){
		int f=floor(x>>1);
		S[f].erase(S[f].find(lose));
		S[f].insert(get);
		x=f;
	}
	return ;
}
void Build(int x,int l,int r){
	if(l==r){S[x].insert(val[rev[l]]);return ;}
	int mid=l+r>>1;
	Build(x<<1,l,mid),Build(x<<1|1,mid+1,r);
	Pushup(x);
	return ;
}
void Modify(int x,int l,int r,int ql,int qr,int k){
	if(ql<=l&&qr>=r){
		Update(x,*S[x].begin(),k);
		S[x].erase(*S[x].begin());S[x].insert(k);
		sum[x]=1;
		return ;
	}
	int mid=l+r>>1;
	if(ql<=mid) Modify(x<<1,l,mid,ql,qr,k);
	if(qr>mid) Modify(x<<1|1,mid+1,r,ql,qr,k);
	return ;
}
int Query(int x,int l,int r,int ql,int qr,int k){
	if(ql<=l&&qr>=r){return S[x].count(k);}
	int mid=l+r>>1;int res=0;
	if(ql<=mid) res+=Query(x<<1,l,mid,ql,qr,k);
	if(qr>mid) res+=Query(x<<1|1,mid+1,r,ql,qr,k);
	return res;
}
void RoadModify(int x,int y,int k){
	while(top[x]!=top[y]){
		if(dep[top[x]]<dep[top[y]]) swap(x,y);
		Modify(1,1,n,dfn[top[x]],dfn[x],k);
		x=fa[top[x]];
	}
	if(dep[x]<dep[y]) swap(x,y);
	Modify(1,1,n,dfn[y],dfn[x],k);
	return ;
}
ll RoadQuery(int x,int y,int k){
	ll res=0;
	while(top[x]!=top[y]){
		if(dep[top[x]]<dep[top[y]]) swap(x,y);
		res+=Query(1,1,n,dfn[top[x]],dfn[x],k);
		x=fa[top[x]];
	}
	if(dep[x]<dep[y]) swap(x,y);
	res+=Query(1,1,n,dfn[y],dfn[x],k);
	return res;
}
int QueryLCA(int x,int y){
	while(top[x]!=top[y]){
		if(dep[top[x]]<dep[top[y]]) swap(x,y);
		x=fa[top[x]];
	}
	if(dep[x]<dep[y]) swap(x,y);
	return y;
}
int main(){
	//freopen("tree.in","r",stdin);
	//freopen("tree.out","w",stdout);
	read(n),read(m);
	for(int i=1;i<=n;i++) read(val[i]);
	for(int i=1;i<n;i++){
		int u,v;
		read(u),read(v);
		Add(u,v),Add(v,u);
	}
	root=1;
	Dfs1(1,0);
	Dfs2(1);
	Build(1,1,n);
	for(int i=1,x,y,k,las=0;i<=m;i++){
		char op[4];
		scanf("%s",op);
		if(op[0]=='C'){
			read(x),read(k);
			x^=las,k^=las;
			Modify(1,1,n,dfn[x],dfn[x],k);
		}
		else{
			read(x),read(y),read(k);
			x^=las,k^=las,y^=las;
			las=RoadQuery(x,y,k);
			write(las),putchar('\n');
		}
	}
	return 0;
}

差分代码:

#include<bits/stdc++.h>
using namespace std;
#define l(x) t[x].l
#define r(x) t[x].r
#define a(x) t[x].add
#define v(x) t[x].val
const int N=1e5+5;
template <typename T>
inline void read(T &x){
	x=0;char ch=getchar();bool f=false;
	while(!isdigit(ch))	f|=ch=='-',ch=getchar();
	while(isdigit(ch))	x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
	x=f?-x:x;
}
template <typename T>
inline void write(T x){
	if(x<0)	putchar('-'),x=-x;
	if(x>9)	write(x/10);
	putchar(x%10^48);
}
struct Segment_Tree{int l,r,add,val;}t[N*100];
map<int,int> val;
int n,q,ans,sum,size,T[N],root[N<<2];
int tot,top,head[N],to[N<<1],nex[N<<1],dep[N],fa[N][20],dfn[N<<1],b[N],e[N];
void add(int u,int v){nex[++tot]=head[u],head[u]=tot,to[tot]=v;}
void dfs(int x){
	dfn[++top]=x;
	for(int i=1;i<=16;i++){
		if((1<<i)<=dep[x]) fa[x][i]=fa[fa[x][i-1]][i-1];
		else break;
	}
	for(int i=head[x];i;i=nex[i]) if(to[i]!=fa[x][0]) fa[to[i]][0]=x,dep[to[i]]=dep[x]+1,dfs(to[i]);
	dfn[++top]=x;
}
int QueryLca(int u,int v){
	if(dep[u]<dep[v]) swap(u,v);
	int temp=dep[u]-dep[v];
	for(int i=0;i<=16;i++) if(temp&(1<<i)) u=fa[u][i];
	for(int i=16;i>=0;i--) if(fa[u][i]!=fa[v][i]) u=fa[u][i],v=fa[v][i];
	return u==v?u:fa[u][0];
}
void PushDown(int p,int l,int r){
	if(!a(p)||l==r) return;
	int temp=a(p);
	if(!l(p)) l(p)=++size;
	if(!r(p)) r(p)=++size;
	a(p)=0,v(l(p))+=temp,a(l(p))+=temp,v(r(p))+=temp,a(r(p))+=temp;
}
void Modify(int &p,int l,int r,int x,int y,int d){
	if(!p) p=++size;
	PushDown(p,l,r);
	if(x==l&&y==r){v(p)+=d,a(p)+=d;return;}
	int mid=(l+r)>>1;
	if(x<=mid) Modify(l(p),l,mid,x,min(y,mid),d);
	if(y>mid) Modify(r(p),mid+1,r,max(x,mid+1),y,d);
}
int Query(int p,int l,int r,int x){
	if(!p) return 0;
	PushDown(p,l,r);
	if(l==r) return v(p);
	int mid=(l+r)>>1;
	if(x<=mid) return Query(l(p),l,mid,x);
	else return Query(r(p),mid+1,r,x);
}
int main(){
	read(n),read(q);
	for(int i=1;i<=n;i++){
		read(T[i]);
		if(!val[T[i]]) val[T[i]]=++sum;
		T[i]=val[T[i]];
	}
	for(int i=1,u,v;i<n;i++) read(u),read(v),add(u,v),add(v,u);
	dfs(1);
	for(int i=1;i<=top;i++){
		if(!b[dfn[i]]) b[dfn[i]]=i;
		else e[dfn[i]]=i;
	}
	for(int i=1;i<=n;i++) Modify(root[T[i]],1,top,b[i],e[i],1);
	for(int i=1,x,y,z;i<=q;i++){
		char op[3];
		scanf("%s",op),read(x),read(y),x^=ans,y^=ans;
		if(op[0]=='Q'){
			read(z),z^=ans;
			int Lca=QueryLca(x,y);
			if(!val[z]){ans=0,puts("0");continue;}
			z=val[z],ans=Query(root[z],1,top,b[x])+Query(root[z],1,top,b[y])-2*Query(root[z],1,top,b[Lca]);
			if(T[Lca]==z) ans++;
			write(ans),putchar('\n');
		}
		if(op[0]=='C'){
			if(!val[y]) val[y]=++sum;
			y=val[y],Modify(root[T[x]],1,top,b[x],e[x],-1),Modify(root[y],1,top,b[x],e[x],1),T[x]=y;
		}
	}
}
posted @ 2021-04-16 16:06  __Anchor  阅读(32)  评论(0编辑  收藏  举报