• BZOJ4999: This Problem Is Too Simple!树链剖分+动态开点线段树


    题目大意:将某个节点的颜色变为x,查询i,j路径上多少个颜色为x的点...

    其实最开始一看就是主席树+树状数组+DFS序...但是过不去...MLE+TLE BY FCWWW

    其实树剖裸的一批...只是在树剖上套一个动态开点的线段树就可以了...很显然的...就是注意一下细节问题,还有Map这种东西,还是不要乱用的说...

    附上代码:

    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <cstring>
    #include <cstdlib>
    #include <queue>
    #include <iostream>
    #include <map>
    using namespace std;
    #define N 100005
    #define lson l,m,tr[rt].ls
    #define rson m+1,r,tr[rt].rs
    struct edge{int to,next;}e[N<<1];
    struct node{int ls,rs,siz;}tr[N*40];
    int rot[N],n,Q,cnt,a[N],head[N],son[N],fa[N],dep[N],siz[N],anc[N],idx[N],tims;
    void add(int x,int y){e[cnt]=(edge){y,head[x]};head[x]=cnt++;}
    void Update(int x,int c,int l,int r,int &rt)
    {
    	if(!rt)rt=++cnt;tr[rt].siz+=c;if(l==r)return ;int m=(l+r)>>1;
    	if(m>=x)Update(x,c,lson);else Update(x,c,rson);
    }
    void dfs1(int x,int from)
    {
    	fa[x]=from,dep[x]=dep[from]+1,siz[x]=1;
    	for(int i=head[x];i!=-1;i=e[i].next)
    	{
    		int to1=e[i].to;
    		if(to1!=from)
    		{
    			dfs1(to1,x);siz[x]+=siz[to1];
    			if(siz[son[x]]<siz[to1])son[x]=to1;
    		}
    	}
    }
    void dfs2(int x,int top)
    {
    	anc[x]=top;idx[x]=++tims;
    	if(son[x])dfs2(son[x],top);
    	for(int i=head[x],to1;i!=-1;i=e[i].next)
    	{
    		if((to1=e[i].to)!=fa[x]&&to1!=son[x])dfs2(to1,to1);
    	}
    }
    int query(int L,int R,int l,int r,int rt)
    {
    	if(L<=l&&r<=R)return tr[rt].siz;int m=(l+r)>>1,ret=0;
    	if(L<=m)ret+=query(L,R,lson);if(m<R)ret+=query(L,R,rson);return ret;
    }
    int get_lca(int x,int y,int c)
    {
    	int ret=0;
    	while(anc[x]!=anc[y])
    	{
    		if(dep[anc[x]]<dep[anc[y]])swap(x,y);
    		ret+=query(idx[anc[x]],idx[x],1,n,rot[c]);
    		x=fa[anc[x]];
    	}if(dep[x]>dep[y])swap(x,y);
    	return ret+query(idx[x],idx[y],1,n,rot[c]);
    }
    map<int ,int>mp;int tot=0,S[N],top,b[N];char s[2];
    int main()
    {
    	scanf("%d%d",&n,&Q);memset(head,-1,sizeof(head));
    	for(int i=1,x;i<=n;i++)
    	{
    		scanf("%d",&x);b[i]=x;
    		if(mp.find(x)==mp.end())mp[x]=++tot;
    		a[i]=mp[x];
    	}for(int i=1,x,y;i<n;i++)scanf("%d%d",&x,&y),add(x,y),add(y,x);cnt=0;
    	dfs1(1,0);dfs2(1,1);for(int i=1;i<=n;i++)Update(idx[i],1,1,n,rot[a[i]]);
    	while(Q--)
    	{
    		int x,y,z;scanf("%s%d%d",s,&x,&y);
    		if(s[0]=='C')
    		{
    			Update(idx[x],-1,1,n,rot[a[x]]);
    			if(tr[rot[a[x]]].siz==0)S[++top]=a[x],mp.erase(mp.find(b[x]));b[x]=y;
    			if(mp.find(y)==mp.end())
    			{
    				if(top)mp[y]=S[top--];
    				else mp[y]=++tot;
    			}y=mp[y];
    			Update(idx[x],1,1,n,rot[y]);a[x]=y;
    		}else
    		{
    			scanf("%d",&z);
    			if(mp.find(z)==mp.end()){puts("0");continue;}
    			printf("%d
    ",get_lca(x,y,mp[z]));
    		}
    	}
    }
    

      

  • 相关阅读:
    Centos 5.5 Lamp源码包安装编译 新风宇宙
    Linux系统日志管理 新风宇宙
    ubuntu设置时区,网上同步时间 新风宇宙
    ubuntu vim输入中文设置(SecureCRT下) 新风宇宙
    DIV+CSS容易犯的十个错误 新风宇宙
    apache性能优化 新风宇宙
    java里面main函数为什么要用static修饰
    如何设计mysql数据库和数据表
    PHP 图片验证码
    PHP免费空间选择方法概述
  • 原文地址:https://www.cnblogs.com/Winniechen/p/9241850.html
Copyright © 2020-2023  润新知