hdu4358 树形转线性 线段树

来源:互联网 发布:淘宝智能客服 编辑:程序博客网 时间:2024/06/12 22:58

题意:给定了一棵树和树上每一个节点的权值 然后询问是给出子树顶点求子树中出现k次的节点权值的个数

解法:把树形先转化成线性的 然后离线所有询问 不要忘了把树上节点的权值离散化 弄完之后就直接往

扫就可以了  当某一种权值>=k时才进行维护

#pragma comment(linker,"/STACK:102400000,102400000")#include<cstdio>#include<vector>#include<stack>#include<algorithm>using namespace std;#define rep(i,st,ed) for(int i=st;i<=ed;++i)#define ls (rt<<1)#define rs (rt<<1|1)#define mid ((l+r)>>1)#define maxn 111111vector<int>g[maxn];int L[maxn],R[maxn],tot,val[maxn],num[maxn],head[maxn],vis[maxn],n;void dfs(int u,int f){    L[u]=++tot;    num[tot]=val[u];    for(int i=0;i<g[u].size();++i){        int v=g[u][i];        if(v==f)continue;        dfs(v,u);    }    R[u]=tot;}struct node{    int v,l,r,id;}_q[maxn];int cmp(node x,node y){return x.r<y.r;}int add[maxn<<2];inline void down(int rt){    if(add[rt]){        add[ls]+=add[rt],add[rs]+=add[rt];        add[rt]=0;    }}inline void build(int rt,int l,int r){    add[rt]=0;if(l==r)return ;    build(ls,l,mid);    build(rs,mid+1,r);}inline void ins(int rt,int l,int r,int L,int R,int w){    if(L<=l&&r<=R){add[rt]+=w;return ;}    down(rt);    if(L<=mid)ins(ls,l,mid,L,R,w);    if(mid<R)ins(rs,mid+1,r,L,R,w);}inline int query(int rt,int l,int r,int pos){    if(l==r)return add[rt];    down(rt);    if(pos<=mid)return query(ls,l,mid,pos);    return query(rs,mid+1,r,pos);}int x[maxn];vector<int>pos[maxn];int ans[maxn];int main()  {    int t,_=0,k,u,v,q;    scanf("%d",&t);    while(t--) {        scanf("%d%d",&n,&k);        tot=0;        rep(i,1,n){            scanf("%d",&val[i]),x[i]=val[i];            g[i].clear(),pos[i].clear();        }        rep(i,1,n-1){            scanf("%d%d",&u,&v);            g[u].push_back(v),g[v].push_back(u);        }        sort(x+1,x+1+n);                int  cnt=(int)(unique(x+1,x+n+1)-x-1);        for(int i=1;i<=n;i++)val[i]=(int)(lower_bound(x+1,x+cnt+1,val[i])-x);                dfs(1,-1);                scanf("%d",&q);        rep(i,0,q-1){            scanf("%d",&_q[i].v);            _q[i].l=L[_q[i].v];_q[i].r=R[_q[i].v];            _q[i].id=i;        }        sort(_q,_q+q,cmp);build(1,1,tot);        int cur=0;        rep(i,1,tot){            int va=num[i];            pos[va].push_back(i);            int sz=(int)pos[va].size();            if(sz>=k){                if(sz==k)ins(1,1,tot,1,pos[va][sz-k],1);                else{                    ins(1,1,tot,1,pos[va][sz-k-1],-1);                    ins(1,1,tot,pos[va][sz-k-1]+1,pos[va][sz-k],1);                }            }            while(cur<q&&_q[cur].r==i){                ans[_q[cur].id]=query(1,1,tot,_q[cur].l);                ++cur;            }        }        if(_)puts("");        printf("Case #%d:\n",++_);        rep(i,0,q-1)printf("%d\n",ans[i]);    }    return 0;}

0 0