hdu 4358 Boring counting(dfs序+莫队算法)

来源:互联网 发布:node v6.9.4 x64.msi 编辑:程序博客网 时间:2024/05/17 04:16

题意:给出一棵树,每个结点有一个权值,有q个查询,查询以u的子树中出现的相同权值的次数为k的数的个数。

思路:首先利用dfs可以把某个结点的子树转化成一个线性区间,然后就可以开心的用莫队搞啦~写完看了看网上的做法,发现大部分都是用线段树或树状数组过的,方法也比较巧妙……不过还是莫队比较好写啊,某些情况下莫队真是神器,时间也不太糟糕800ms+

代码:

#pragma comment(linker, "/STACK:102400000,102400000")#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<algorithm>#include<map>#include<queue>#include<stack>#include<cmath>#include<vector>#define inf 0x3f3f3f3f#define Inf 0x3FFFFFFFFFFFFFFFLL#define eps 1e-9#define pi acos(-1.0)using namespace std;typedef long long ll;const int maxn=100000+10;const int size=255;struct Edge{    int v,next;    Edge(){}    Edge(int v,int next):v(v),next(next){}}edges[maxn];struct Query{    int L,R,id;    Query(){}    Query(int L,int R,int id):L(L),R(R),id(id){}    bool operator <(const Query & a) const    {        if(L/size!=a.L/size) return L<a.L;        return R<a.R;    }}querys[maxn];int val[maxn],num[maxn],cnt[maxn],Lv[maxn],Rv[maxn];int head[maxn],ans[maxn],nEdge,dfs_clock,n,m,k,tot;map<int,int>mp;void Init(){    mp.clear();    memset(head,0xff,sizeof(head));    nEdge=-1;dfs_clock=0;    memset(cnt,0,sizeof(cnt));}void AddEdges(int u,int v){    edges[++nEdge]=Edge(v,head[u]);    head[u]=nEdge;    edges[++nEdge]=Edge(u,head[v]);    head[v]=nEdge;}void dfs(int u,int fa){    Lv[u]=++dfs_clock;    val[dfs_clock]=num[u];    for(int k=head[u];k!=-1;k=edges[k].next)    {        int v=edges[k].v;        if(v==fa) continue;        dfs(v,u);    }    Rv[u]=dfs_clock;}inline void Add(int x){    if(cnt[val[x]]==k) tot--;    if(cnt[val[x]]+1==k) tot++;    cnt[val[x]]++;}inline void Dec(int x){    if(cnt[val[x]]==k) tot--;    if(cnt[val[x]]-1==k) tot++;    cnt[val[x]]--;}void solve(){    tot=0;    int l=1,r=0;    for(int i=0;i<m;++i)    {        while(querys[i].L<l) Add(--l);        while(querys[i].R<r) Dec(r--);        while(querys[i].L>l) Dec(l++);        while(querys[i].R>r) Add(++r);        ans[querys[i].id]=tot;    }}int main(){    //freopen("in.txt","r",stdin);    //freopen("out.txt","w",stdout);    int t,tcase=0;    scanf("%d",&t);    while(t--)    {        if(tcase) printf("\n");        tcase++;        Init();        scanf("%d%d",&n,&k);        int u=0,v;        for(int i=1;i<=n;++i)        {            scanf("%d",&v);            if(mp[v]) num[i]=mp[v];            else num[i]=mp[v]=++u;        }        for(int i=1;i<n;++i)        {            scanf("%d%d",&u,&v);            AddEdges(u,v);        }        dfs(1,-1);        scanf("%d",&m);        for(int i=0;i<m;++i)        {            scanf("%d",&u);            querys[i]=Query(Lv[u],Rv[u],i);        }        sort(querys,querys+m);        solve();        printf("Case #%d:\n",tcase);        for(int i=0;i<m;++i)            printf("%d\n",ans[i]);    }    return 0;}

0 0
原创粉丝点击