zoukankan      html  css  js  c++  java
  • 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('
    ');
    		}
    	}
    	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('
    ');
    		}
    		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;
    		}
    	}
    }
    
  • 相关阅读:
    Apache Spark源码走读之8 -- Spark on Yarn
    Apache Spark源码走读之7 -- Standalone部署方式分析
    Apache Spark源码走读之6 -- 存储子系统分析
    Linux服务器--所有用户登陆操作命令审计
    Linux--top命令查看系统状态,所有值讲解
    docker --help 详解
    Linux下使用《du》命令查看某文件及目录的大小
    Linux查看CPU《型号..》《内存..》《硬盘..》《系统..》
    Linux下 cmatrix的安装和使用
    CentOS 6.3下部署LVS(NAT)+keepalived实现高性能高可用负载均衡
  • 原文地址:https://www.cnblogs.com/Akmaey/p/14667420.html
Copyright © 2011-2022 走看看