cf#221-div1-D - Tree and Queries-dfs序+莫队算法

来源:互联网 发布:天津网络推广公司 编辑:程序博客网 时间:2024/05/22 12:31

http://codeforces.com/contest/375/problem/D



给一棵有根树,每个节点有个颜色,每次询问 v,k,即v节点为根的子树中,有多少种颜色,出现的次数超过k。


对于查询v的子树,先转为dfs序。


对于出现次数超过k的答案,我们另外用一个数组维护,即当color1个数增加时,那么num[ color1_num ]++, 

减少时则 num[ color1_num ]--

这样我们就能直接得到  num[k]为出现次数超过k次的颜色种类。


这样的话,可以发现对于区间【l,r】的转移符合使用莫队算法的条件,则可以用莫队算法,分块,区间排序。


复杂度 (q+n)sqrtn  跑了233ms

#include <cstdio>#include <cmath>#include <cstring>#include <string>#include <algorithm>#include <queue>#include <map>#include <set>#include <vector>#include <iostream>using namespace std;#define N 100100typedef long long ll;int a[N], cnt[N];ll  ans[N], res;int L, R;vector< int > mp[N];int in[N];int out[N];int id=0;int col[N];int who[N];int vis[N];int num[N];void dfs(int x){    int i;    in[x]=++id;    who[id]=x;    vis[x]=1;    for (i=0; i<mp[x].size(); i++)    {        int v=mp[x][i];        if (!vis[v])        dfs(v);    }    out[x]=id;}struct node{    int x, y, l, p,k;} q[N];bool cmp(const node &x, const node &y){    if (x.l == y.l) return x.y < y.y;    return x.l < y.l;}void query(int x, int y, int flag ){    if (flag)    {        for (int i=x; i<L; i++)        {            cnt[ col[who[i]] ]++;            num[cnt[ col[who[i]] ]]++;        }        for (int i=L; i<x; i++)        {            num[cnt[ col[who[i]] ]]--;            cnt[ col[who[i]] ]--;        }        for (int i=y+1; i<=R; i++)        {            num[cnt[ col[who[i]] ]]--;            cnt[ col[who[i]] ]--;        }        for (int i=R+1; i<=y; i++)        {            cnt[ col[who[i]] ]++;            num[cnt[ col[who[i]] ]]++;        }    }    else    {        for (int i=x; i<=y; i++)        {            cnt[ col[who[i]] ]++;            num[cnt[ col[who[i]] ]]++;        }    }    L = x, R = y;}int main(){    int n, m;    scanf("%d%d", &n, &m);    int x,y;    for (int i=1; i<=n ; i++)        scanf("%d",&col[i]);    for (int i=1; i<=n-1; i++)    {        scanf("%d%d", &x,&y);        mp[x].push_back(y);        mp[y].push_back(x);    }    dfs(1);    int block_size = sqrt(1.0*n);    for (int i=0; i<m; i++)    {        scanf("%d%d", &x,&y);        q[i].x=in[x];        q[i].y=out[x];        q[i].l = q[i].x / block_size;        q[i].p = i;        q[i].k=y;    }    sort(q, q+m, cmp);    res = 0;    for (int i=0; i<m; i++)    {        query(q[i].x, q[i].y, i);        ans[q[i].p] = num[q[i].k];    }    for (int i=0; i<m; i++) printf("%I64d\n", ans[i]);    return 0;}


0 0
原创粉丝点击