zoukankan      html  css  js  c++  java
  • 一本通1760:树上数颜色

    链接

    将相同颜色的点按 (dfs) 序排序,在树上差分。
    因为有颜色和 (dfs) 序两个维度,用树状数组套动态开点线段树维护。

    #pragma G++ optimize(2)
    #include<bits/stdc++.h>
    #define IL inline
    #define LL long long
    using namespace std;
    const int N=1e5+3;
    struct hh{int to,nxt;}e[N<<1];
    int n,m,fir[N],num,col[N],dfn[N],rev[N],dep[N],son[N],siz[N],fa[N],top[N];
    int cnt,ls[N*400],rs[N*400],sum[N*400],rt[N],ans;
    set<int>st[N];
    set<int>::iterator it1,it2,it3,it4;
    IL int in(){
    	char c;int f=1;
    	while((c=getchar())<'0'||c>'9')
    	  if(c=='-') f=-1;
    	int x=c-'0';
    	while((c=getchar())>='0'&&c<='9')
    	  x=x*10+c-'0';
    	return x*f;
    }
    IL void link(int x,int y){e[++num]=(hh){y,fir[x]},fir[x]=num;}
    void dfs1(int u,int f){
    	fa[u]=f,dep[u]=dep[f]+1,siz[u]=1;
    	for(int i=fir[u],v;v=e[i].to;i=e[i].nxt)
    	  if(v^f){
    	  	dfs1(v,u),siz[u]+=siz[v];
    	  	if(siz[son[u]]<siz[v]) son[u]=v;
    		}
    }
    void dfs2(int u,int t){
    	top[u]=t,rev[dfn[u]=++num]=u;
    	if(son[u]) dfs2(son[u],t);
    	for(int i=fir[u],v;v=e[i].to;i=e[i].nxt)
    	  if(v^fa[u]&&v^son[u]) dfs2(v,v);
    }
    int get_lca(int x,int y){
    	while(top[x]^top[y]) dep[top[x]]<dep[top[y]]?y=fa[top[y]]:x=fa[top[x]];
    	return dep[x]<dep[y]?x:y;
    }
    void mdy(int &o,int l,int r,int u,int op){
    	if(!o) o=++cnt;sum[o]+=op;
    	if(l==r) return;
    	int mid=l+r>>1;
    	if(u<=mid) mdy(ls[o],l,mid,u,op);
    	else mdy(rs[o],mid+1,r,u,op);
    }
    int query(int o,int l,int r,int ll,int rr){
    	if(!o) return 0;
    	if(l>=ll&&r<=rr) return sum[o];
    	int mid=l+r>>1;
    	if(rr<=mid) return query(ls[o],l,mid,ll,rr);
    	if(ll>mid) return query(rs[o],mid+1,r,ll,rr);
    	return query(ls[o],l,mid,ll,rr)+query(rs[o],mid+1,r,ll,rr);
    }
    IL int lb(int x){return x&-x;}
    IL void add(int y,int x,int op){for(;y<=n;y+=lb(y)) mdy(rt[y],1,n,x,op);}
    IL int ask(int y,int l,int r){int res=0;for(;y;y-=lb(y) ) res+=query(rt[y],1,n,l,r);return res;}
    void Add(int x,int c){
    	it1=st[c].insert(dfn[x]).first,it2=st[c].end(),--it2,add(c,dfn[x],1);
    	if(it1!=st[c].begin()) it3=it1,--it3,add(c,dfn[get_lca(rev[*it1],rev[*it3])],-1);
    	if(it1!=it2) it4=it1,++it4,add(c,dfn[get_lca(rev[*it1],rev[*it4])],-1);
    	if(it1!=st[c].begin()&&it1!=it2) add(c,dfn[get_lca(rev[*it3],rev[*it4])],1);
    }
    void Del(int x,int c){
    	it1=st[c].find(dfn[x]),it2=st[c].end(),--it2,add(c,dfn[x],-1);
    	if(it1!=st[c].begin()) it3=it1,--it3,add(c,dfn[get_lca(rev[*it1],rev[*it3])],1);
    	if(it1!=it2) it4=it1,++it4,add(c,dfn[get_lca(rev[*it1],rev[*it4])],1);
    	if(it1!=st[c].begin()&&it1!=it2) add(c,dfn[get_lca(rev[*it3],rev[*it4])],-1);
    	st[c].erase(dfn[x]);
    }
    int Ask(int u,int l,int r){return ask(r,dfn[u],dfn[u]+siz[u]-1)-ask(l-1,dfn[u],dfn[u]+siz[u]-1);}
    int main()
    {
    	int op,t,x,y,c;
    	n=in(),m=in(),op=in();
    	for(int i=1;i<=n;++i) col[i]=in();
    	for(int i=1;i<n;++i)
    	  x=in(),y=in(),
    	  link(x,y),link(y,x);
    	num=0,dfs1(1,0),dfs2(1,1);
    	for(int i=1;i<=n;++i) Add(i,col[i]);
    	while(m--){
    		t=in(),x=in(),y=in();
    		if(op) x^=ans,y^=ans;
    		if(t==1) c=op?in()^ans:in(),printf("%d
    ",ans=Ask(x,y,c));
    		else Del(x,col[x]),col[x]=y,Add(x,col[x]);
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    重读数据结构——严蔚敏C语言版
    Tcp/Ip网络通讯初探
    XMLHttpRequest post 传递多个参数及服务器端读取
    HDOJ 1106 排序 (字符串处理)
    用Java创建数组工具类ArrayTool
    自己动手编写一个VS插件(三)——创建工具栏之一
    「译」JavaScript 的怪癖 1:隐式类型转换
    javascript 中强制执行 toString()
    VS 2008的64位编译环境的安装和使用
    计算机神书『编码:隐匿在计算机软硬件背后的语言』
  • 原文地址:https://www.cnblogs.com/yiqiAtiya/p/13920846.html
Copyright © 2011-2022 走看看