SPOJ COT2(Count on a tree II) 树上莫队

题意:给你一棵N个节点的树,每个节点有一个权值,对于M个询问(u,v),你需要回答u和v这两个节点间有多少种不同的点权。

思路:1点权比较大需要离散化。2对这棵树求其dfs序分块,3对m组询问的L和R求lca,4莫队,lca需要特殊处理。

#include 

using namespace std;
const int maxn=40050;
const int maxm=1e5+10;
int n,m,t;

struct node{
    int id,l,r,extra;
}s[maxm];
int block[maxn*2];
bool cmp(const node &a,const node &b)
{
    if(block[a.l]!=block[b.l]) return a.lg[maxn];
int tim=0;
void dfs(int u,int pre)
{
    in[u]=++tim;
    p[tim]=u;
    for(int i=0;i=0;i--)
        if (dep[fa[x][i]]>=dep[y])
            x=fa[x][i];
    if (x==y) return x;
    for(int i=20;i>=0;i--)
        if (fa[x][i]!=fa[y][i])
            x=fa[x][i],y=fa[y][i];
    return fa[x][0];
}

int vis[maxn];
int sum;
void expand(int x)
{
    vis[p[x]]^=1;
    if (vis[p[x]])
    {
        c[a[p[x]]]++;
        if (c[a[p[x]]]==1) sum++;
    }
    else
    {
        c[a[p[x]]]--;
        if (c[a[p[x]]]==0) sum--;
    }
}

int ans[maxm];
void Modui()
{
    int l=1,r=0;
    sum=0;
    for(int i=1;i<=m;i++)
    {
        while (s[i].lr) expand(++r);
        while (s[i].l>l) expand(l++);
        while (s[i].rs[i].r)
                swap(s[i].l,s[i].r);
        }
        sort(s+1,s+m+1,cmp);
        Modui();
        for(int i=1;i<=m;i++)
            printf("%d\n",ans[i]);
    }
    return 0;
}

你可能感兴趣的:(树上莫队,莫队)