• 数树数


    数树数

    题目描述

     

          给定一棵N个节点的树,标号从1~N。每个点有一个权值。要求维护两种操作:

    1. C i x(0<=x<2^31) 表示将i点权值变为x

    2. Q i j x(0<=x<2^31) 表示询问i到j的路径上有多少个值为x的节点

     

     

    输入

     

    对于每个测试点,第一行有两个整数N,Q,分别表示树上节点个数询问个数。下面一行N个整数,表示初始时每个点的权值。接下来N-1行,每行两个整数x,y,表示x与y之间有边。接下来Q行,每行表示一个操作,操作的描述已经在题目描述中给出。

     

    对于30%的数据,N,Q<=1000;

    对于100%的数据,N<=100000,Q<=200000。

     

     

     

     

    输出

     

             对于每个Q输出一行所求的答案。

     

     

    样例输入

    5 6
    10 20 30 40 50
    1 2
    1 3
    3 4
    3 5
    Q 2 3 40
    C 1 40
    Q 2 3 40
    Q 4 5 30
    C 3 10
    Q 4 5 30
    

    样例输出

    0
    1
    1
    0

    考虑对每个权值开线段树,下标为点的编号

    维护点的数目和

    修改就把相应的两种权值的树拉出来

    查询就树剖+区间查询

    树不能开满,那就动态开

    似乎很像旅行

    #include<cstdio>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<map>
    #define maxn 100005
    using namespace std;
    int n,T,Q,head[maxn],s[maxn],lsh[maxn*3],dy[maxn*3],t1,t2,tot,fs,total;
    int size[maxn],son[maxn],fa[maxn],top[maxn],deep[maxn],sc,dfsn[maxn],fsy,li,ri,root[maxn*3];
    map<int,int>l;
    char ch;
    struct node{
        int v,nex;
    }e[maxn*2];
    struct no{
        int id,a,b,c;
    }q[maxn*2];
    struct ff{
        int x,ls,rs,l,r;
    }tree[maxn*3*21];
    void lj(int t1,int t2){
        total++;e[total].v=t2;e[total].nex=head[t1];head[t1]=total;
    }
    void Lsh(){
        sort(lsh+1,lsh+tot+1);
        lsh[0]=-1;
        for(int i=1;i<=tot;i++){
            if(lsh[i]!=lsh[i-1])l[lsh[i]]=++fs,dy[fs]=lsh[i];
        }
    }
    void dfs1(int k,int fath){
        fa[k]=fath;deep[k]=deep[fath]+1;
        int sz=0,gp=-1;
        for(int i=head[k];i;i=e[i].nex){
            if(e[i].v!=fath){
                dfs1(e[i].v,k);
                sz+=size[e[i].v];
                if(gp==-1)gp=e[i].v;
                if(size[e[i].v]>size[gp])gp=e[i].v;
            }
        }
        size[k]=sz+1;son[k]=gp;
    }
    void dfs2(int k){
        dfsn[k]=++sc;
        if(son[k]!=-1){
            top[son[k]]=top[k];
            dfs2(son[k]);
        }
        for(int i=head[k];i;i=e[i].nex){
            if(e[i].v!=fa[k]&&e[i].v!=son[k]){
                top[e[i].v]=e[i].v;
                dfs2(e[i].v);
            }
        }
    }
    void wh(int k){
        tree[k].x=tree[tree[k].ls].x+tree[tree[k].rs].x;
    }
    void lian(int &k,int l,int r,int pl,int v){
        if(!k)k=++fsy;
        tree[k].l=l;tree[k].r=r;
        if(l==r){
            tree[k].x+=v;return;
        }
        int mid=l+r>>1;
        if(pl<=mid)lian(tree[k].ls,l,mid,pl,v);
        else lian(tree[k].rs,mid+1,r,pl,v);
        wh(k);
    }
    int ask(int k){
        if(!k)return 0;
        if(tree[k].l>=li&&tree[k].r<=ri){
            return tree[k].x;
        }
        int mid=tree[k].l+tree[k].r>>1;
        int co=0;
        if(li<=mid)co+=ask(tree[k].ls);
        if(ri>mid)co+=ask(tree[k].rs);
        return co;
    }
    int main(){
        cin>>n>>Q;
        for(int i=1;i<=n;i++){
            scanf("%d",&s[i]);
            lsh[++tot]=s[i];
        }
        for(int i=1;i<n;i++){
            scanf("%d%d",&t1,&t2);
            lj(t1,t2);lj(t2,t1);
        }
        for(int i=1;i<=Q;i++){
            scanf(" %c",&ch);
            if(ch=='C'){
                q[i].id=1;
                scanf("%d%d",&q[i].a,&q[i].b);
                lsh[++tot]=q[i].b;
            }
            else {
                scanf("%d%d%d",&q[i].a,&q[i].b,&q[i].c);
                lsh[++tot]=q[i].c;
            }
        }
        Lsh();
        dfs1(1,0);top[1]=1;dfs2(1);
        for(int i=1;i<=n;i++){
            int tmp=l[s[i]];
            lian(root[tmp],1,n,dfsn[i],1);
        }
        for(int i=1;i<=Q;i++){
            if(q[i].id==1){
                int tmp=l[s[q[i].a]];
                lian(root[tmp],1,n,dfsn[q[i].a],-1);
                s[q[i].a]=q[i].b;
                tmp=l[s[q[i].a]];
                lian(root[tmp],1,n,dfsn[q[i].a],1);
            }
            else {
                int sum=0,x,y,tmp;
                x=q[i].a,y=q[i].b;tmp=l[q[i].c];
                t1=top[x],t2=top[y];
                while(t1!=t2){
                    if(deep[t1]<deep[t2])swap(x,y),swap(t1,t2);
                    li=dfsn[t1];ri=dfsn[x];
                    sum+=ask(root[tmp]);
                    x=fa[t1];t1=top[x];
                } 
                if(deep[x]<deep[y])swap(x,y);
                li=dfsn[y],ri=dfsn[x];
                sum+=ask(root[tmp]);
                printf("%d
    ",sum);
            }
        }
        return 0;
    }
  • 相关阅读:
    表单
    表格
    浮动与定位实例中的问题
    浮动与定位
    BFC的布局规则以及触发条件
    发布为知笔记到博客
    处理为知笔记样式与博客园样式冲突
    文字处理
    块元素并行的问题
    标签嵌套规则
  • 原文地址:https://www.cnblogs.com/liankewei/p/10358843.html
Copyright © 2020-2023  润新知