zoukankan      html  css  js  c++  java
  • SPOJ.COT2 Count on a tree II(树上莫队)

    题目链接(同上一题苹果树)

    为什么第10个点T了一晚上。。
    下面那个却AC了?跑的也不慢。

    TLE:

    /*
    在DFS序做莫队 
    当一个点不是另一个点的LCA时,需要加上它们LCA的贡献 
    */
    #include <cmath>
    #include <cstdio>
    #include <cctype>
    #include <algorithm>
    #define gc() getchar()
    //#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
    const int N=5e4+5,M=1e5+5,MAXIN=2e6;
    
    int n,m,size,Enum,H[N],nxt[N<<1],to[N<<1],dep[N],fa[N],top[N],son[N],sz[N];
    int Now,Ans[M],seq[N<<1],in[N],out[N],id,A[N],ref[N],cnt,tm[N];
    //char IN[MAXIN],*SS=IN,*TT=IN;
    bool vis[N];
    struct Ques
    {
    	int l,r,lca,id;
    	bool operator <(const Ques &a)const{
    		return l/size<a.l/size?r<a.r:l/size<a.l/size;
    	}
    }q[M];
    
    //inline int read()
    //{
    //	int now=0,f=1;register char c=gc();
    //	for(;!isdigit(c);c=gc()) if(c=='-') f=-1;
    //	for(;isdigit(c);now=now*10+c-'0',c=gc());
    //	return now*f;
    //}
    inline void AddEdge(int u,int v)
    {
    	to[++Enum]=v, nxt[Enum]=H[u], H[u]=Enum;
    	to[++Enum]=u, nxt[Enum]=H[v], H[v]=Enum;
    }
    int Find(int x)
    {
    	int l=1,r=cnt,mid;
    	while(l<r)
    		if(ref[mid=l+r>>1]>=x) r=mid;
    		else l=mid+1;
    	return l;
    }
    void Discrete()
    {
    //	for(int i=1; i<=n; ++i) A[i]=ref[i]=read();
    	for(int i=1; i<=n; ++i) scanf("%d",&A[i]),ref[i]=A[i];
    	std::sort(ref+1,ref+1+n);
    	cnt=1;
    	for(int i=2; i<=n; ++i)
    		if(ref[i]!=ref[i-1]) ref[++cnt]=ref[i];
    	for(int i=1; i<=n; ++i) A[i]=Find(A[i]);
    }
    void Pre_DFS(int x)
    {
    	in[x]=++id, seq[id]=x, sz[x]=1;
    	int mx=0;
    	for(int v,i=H[x]; i; i=nxt[i])
    		if((v=to[i])!=fa[x])
    		{
    			fa[v]=x, dep[v]=dep[x]+1, Pre_DFS(v), sz[x]+=sz[v];
    			if(sz[v]>mx) mx=sz[v],son[x]=v;
    		}
    	out[x]=++id, seq[id]=x;
    }
    void DFS2(int x,int tp)
    {
    	top[x]=tp;
    	if(son[x])
    	{
    		DFS2(son[x],tp);
    		for(int i=H[x]; i; i=nxt[i])
    			if(to[i]!=fa[x]&&to[i]!=son[x])
    				DFS2(to[i],to[i]);
    	}
    }
    int Query_LCA(int x,int y)
    {
    	while(top[x]!=top[y])
    	{
    		if(dep[top[x]]<dep[top[y]]) std::swap(x,y);
    		x=fa[top[x]];
    	}
    	return dep[x]>dep[y]?y:x;
    }
    void Calc(int p)
    {
    	if(vis[p])
    		if(!--tm[A[p]]) --Now;
    		else ;
    	else if(++tm[A[p]]==1) ++Now;
    	vis[p]^=1;
    }
    
    int main()
    {
    //	n=read(),m=read();
    	scanf("%d%d",&n,&m);
    	Discrete();
    //	for(int u,v,i=1; i<n; ++i) u=read(),v=read(),AddEdge(u,v);
    	for(int u,v,i=1; i<n; ++i) scanf("%d%d",&u,&v),AddEdge(u,v);
    	Pre_DFS(1), DFS2(1,1);
    	for(int u,v,w,i=1; i<=m; ++i)
    	{
    //		u=read(),v=read(),w=Query_LCA(u,v);
    		scanf("%d%d",&u,&v),w=Query_LCA(u,v);
    		q[i].id=i;//这要在continue前面。。
    		if(u==v) {q[i].lca=-1; continue;}
    		if(in[u]>in[v]) std::swap(u,v);
    		if(w==u) q[i].l=in[w],q[i].r=in[v],q[i].lca=0;//这部分的LCA不能和u=v时用一样的! 
    //		else if(w==v) q[i].r=in[w],q[i].r=in[u],q[i].lca=0;
    		else q[i].l=out[u],q[i].r=in[v],q[i].lca=in[w];//in[w] not w!
    	}
    	size=sqrt(id), std::sort(q+1,q+1+m);
    	for(int l=1,r=0,i=1; i<=m; ++i)
    		if(q[i].lca==-1) Ans[q[i].id]=1;
    		else
    		{
    			while(l<q[i].l) Calc(seq[l++]);
    			while(l>q[i].l) Calc(seq[--l]);
    			while(r<q[i].r) Calc(seq[++r]);
    			while(r>q[i].r) Calc(seq[r--]);
    			if(q[i].lca) Calc(seq[q[i].lca]);//seq[in[lca]] not in[lca]!
    			Ans[q[i].id]=Now;
    			if(q[i].lca) Calc(seq[q[i].lca]);
    		}
    	for(int i=1; i<=m; ++i) printf("%d
    ",Ans[i]);
    
    	return 0;
    }
    

    **AC: **2.21s 8.5M

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    
    typedef long long ll;
    const int N = 50010;
    struct edge
    {
        int to, next;
    }g[N*2];
    int n, m, unit;
    struct node
    {
        int l, r, anc, id;
        bool operator <(const node &b)const {return l/unit != b.l/unit ? l/unit < b.l/unit : r < b.r;}
    }q[N*2];
    int arr[N], ref[N];
    int cnt, head[N];
    int dep[N];
    int in[N], out[N], seq[N*2], num;
    int res[N*2], tmp, ver[N];
    bool vis[N];
    void add_edge(int v, int u)
    {
        g[cnt].to = u, g[cnt].next = head[v], head[v] = cnt++;
    }
    void dfs(int v)
    {
        in[v] = ++num;
        seq[num] = v;
        for(int i = head[v]; i != -1; i = g[i].next)
        {
            int u = g[i].to;
            if(! dep[u])
                dep[u] = dep[v] + 1, dfs(u);
        }
        out[v] = ++num;
        seq[num] = v;
    }
    namespace Subd
    {
    	int dep[N],fa[N],top[N],son[N],sz[N];
    	void Pre_DFS(int x)
    	{
    		sz[x]=1;
    		int mx=0;
    		for(int v,i = head[x]; i != -1; i = g[i].next)
    			if((v=g[i].to)!=fa[x])
    			{
    				fa[v]=x, dep[v]=dep[x]+1, Pre_DFS(v), sz[x]+=sz[v];
    				if(sz[v]>mx) mx=sz[v],son[x]=v;
    			}
    	}
    	void DFS2(int x,int tp)
    	{
    		top[x]=tp;
    		if(son[x])
    		{
    			DFS2(son[x],tp);
    			for(int v,i = head[x]; i != -1; i = g[i].next)
    				if((v=g[i].to)!=fa[x]&&v!=son[x])
    					DFS2(v,v);
    		}
    	}
    	int Query_LCA(int x,int y)
    	{
    		while(top[x]!=top[y])
    		{
    			if(dep[top[x]]<dep[top[y]]) std::swap(x,y);
    			x=fa[top[x]];
    		}
    		return dep[x]>dep[y]?y:x;
    	}
    }
    void Calc(int p)
    {
    	if(vis[p])
    		if(!--ver[arr[p]]) --tmp;
    		else ;
    	else if(++ver[arr[p]]==1) ++tmp;
    	vis[p]^=1;
    }
    int tot;
    int Find(int x)
    {
    	int l=1,r=tot,mid;
    	while(l<r)
    		if(ref[mid=l+r>>1]>=x) r=mid;
    		else l=mid+1;
    	return l;
    }
    void Discrete()
    {
    	for(int i=1; i<=n; ++i) ref[i]=arr[i];
    	sort(ref+1,ref+1+n);
    	tot=1;
    	for(int i=2; i<=n; ++i)
    		if(ref[i]!=ref[i-1]) ref[++tot]=ref[i];
    	for(int i=1; i<=n; ++i) arr[i]=Find(arr[i]);
    }
    //bool cmp(node a, node b){return a.l/unit != b.l/unit ? a.l/unit < b.l/unit : a.r < b.r;}
    
    void solve()
    {
        int a, b;
        for(int i = 1; i <= n; i++)
            scanf("%d", &arr[i]);
        Discrete();
        cnt = 0;
        memset(head, -1, sizeof head);
        for(int i = 1; i <= n - 1; i++) //存树
            scanf("%d%d", &a, &b), add_edge(a, b), add_edge(b, a);
        memset(dep, 0, sizeof dep);
        dep[1] = 1;
        num = 0;
        dfs(1);
        Subd::Pre_DFS(1), Subd::DFS2(1,1);
        for(int u,v,i = 1; i <= m; i++)
        {
            scanf("%d%d", &u, &v);
            q[i].id = i;
            if(u == v) q[i].anc = -1; //特殊标记,此时公共祖先应该为1
            else
            {
                int w=Subd::Query_LCA(u,v);
                if(in[u]>in[v]) swap(u,v);
    			if(w==u) q[i].l=in[w],q[i].r=in[v],q[i].anc=0;
    			else q[i].l=out[u],q[i].r=in[v],q[i].anc=w;
            }
        }
        unit = sqrt(num);
        sort(q + 1, q + 1 + m);//分块排序
        int l = 1, r = 0;
        tmp = 0;
        for(int i = 1; i <= m; i++)
        	if(q[i].anc==-1) res[q[i].id]=1;
    		else
    		{
    			while(l<q[i].l) Calc(seq[l++]);
    			while(l>q[i].l) Calc(seq[--l]);
    			while(r<q[i].r) Calc(seq[++r]);
    			while(r>q[i].r) Calc(seq[r--]);
    			if(q[i].anc>0) Calc(seq[in[q[i].anc]]);
    			res[q[i].id]=tmp;
    			if(q[i].anc>0) Calc(seq[in[q[i].anc]]);
    		}
        for(int i = 1; i <= m; i++) printf("%d
    ", res[i]);
    }
    int main()
    {
        scanf("%d%d", &n, &m);
        solve();
        return 0;
    }
    
  • 相关阅读:
    VS配置C++依赖包
    BNP Paribas Cardif Claims Management
    【Weiss】【第04章】AVL树例程
    【Weiss】【第04章】二叉搜索树例程
    【Weiss】【第03章】增补附注
    【Weiss】【第03章】练习3.26:双端队列
    【Weiss】【第03章】练习3.25:数组模拟队列
    【Weiss】【第03章】练习3.22、3.23、3.24:无代码题,栈的思考题
    【Weiss】【第03章】练习3.21:单数组模拟双栈
    javaweb学习(十)—— HttpServletRequest对象(一)
  • 原文地址:https://www.cnblogs.com/SovietPower/p/8476895.html
Copyright © 2011-2022 走看看