• bzoj 4999: This Problem Is Too Simple!


    Description

    给您一颗树,每个节点有个初始值。
    现在支持以下两种操作:
    1. C i x(0<=x<2^31) 表示将i节点的值改为x。
    2. Q i j x(0<=x<2^31) 表示询问i节点到j节点的路径上有多少个值为x的节点。
     

    Input

    第一行有两个整数N,Q(1 ≤N≤ 100,000;1 ≤Q≤ 200,000),分别表示节点个数和操作个数。
    下面一行N个整数,表示初始时每个节点的初始值。
    接下来N-1行,每行两个整数x,y,表示x节点与y节点之间有边直接相连(描述一颗树)。
    接下来Q行,每行表示一个操作,操作的描述已经在题目描述中给出。
     

     

    Output

    对于每个Q输出单独一行表示所求的答案。
     

     

    Sample Input

    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

    Sample Output

    0
    1
    1
    0
    ————————————————————————————
    这道题我写的扫描线 
    我们把一个询问(u->v)拆成四个 
    设根为1 
    询问的答案就是1->u + 1->v - 1->lca(u,v) 1-fa[lca] 
    然后修改的影响范围只有这个点的子树 这个可以用dfs序+树状数组实现
    然后我们每一种权值建一棵树(权值需要离散化) 当然因为如果每次都初始化树状数组肯定会T
    这里我利用了时间戳  这样之后就解决问题了 就是代码可能有点复杂QAQ
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    const int M=1e6+7,mod=9875321;
    int read(){
        int ans=0,f=1,c=getchar();
        while(c<'0'||c>'9'){if(c=='-') f=-1; c=getchar();}
        while(c>='0'&&c<='9'){ans=ans*10+(c-'0'); c=getchar();}
        return ans*f;
    }
    int n,m,k,v[M],l[M],r[M],pos[M];
    int first[M],cnt,ans[M],mark[M];
    struct node{int to,next;}e[2*M];
    void ins(int a,int b){e[++cnt]=(node){b,first[a]}; first[a]=cnt;}
    void insert(int a,int b){ins(a,b); ins(b,a);}
    int dep[M],f[M][25],sum;
    void dfs(int x){
        l[x]=pos[x]=++sum;
        for(int i=1;(1<<i)<=dep[x];i++) f[x][i]=f[f[x][i-1]][i-1];
        for(int i=first[x];i;i=e[i].next){
            int now=e[i].to;
            if(!dep[now]){
                dep[now]=dep[x]+1;
                f[now][0]=x;
                dfs(now);
            }
        }r[x]=sum;
    }
    int find(int x,int y){
        if(dep[x]<dep[y]) std::swap(x,y);
        int d=dep[x]-dep[y];
        for(int i=0;(1<<i)<=d;i++) if(1<<i&d) x=f[x][i];
        if(x==y) return x;
        for(int i=20;i>=0;i--) 
            if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
        return f[x][0];
    }
    struct P{int s,x,T;};
    std::vector<P>e1[M];
    struct Q{int l,r,T;};
    std::vector<Q>e2[M];
    int star[mod],cnth;
    struct H{int to,next;}hash[M];
    int get(int x){
        int w=x%mod;
        for(int i=star[w];i;i=hash[i].next) if(hash[i].to==x) return i;
        cnth++; hash[cnth].to=x; hash[cnth].next=star[w]; star[w]=cnth;
        return cnth;
    }
    char c[5];
    int s[M],now[M];
    int lowbit(int x){return x&-x;}
    void add(int x,int ss){
        while(x<=n){
            if(now[x]!=k) now[x]=k,s[x]=0;
            s[x]+=ss; 
            x+=lowbit(x);
        }
    }
    int query(int x){
        int ans=0;
        while(x){
            if(now[x]==k) ans+=s[x];
            x-=lowbit(x);
        }
        return ans;
    }
    int main(){
        n=read(); m=read();
        for(int i=1;i<=n;i++){
            v[i]=get(read());
            e1[v[i]].push_back((P){1,i,0});
        }
        int x,y;
        for(int i=1;i<n;i++) x=read(),y=read(),insert(x,y);
        dep[1]=1; dfs(1);
        for(int i=1;i<=m;i++){
            scanf("%s",c);
            if(c[0]=='C'){
                x=read(); k=get(read());
                if(v[x]==k) continue;
                e1[k].push_back((P){1,x,i});
                e1[v[x]].push_back((P){-1,x,i});
                v[x]=k;
            }
            else{
                mark[i]=1;
                x=read(); y=read(); k=get(read());
                e2[k].push_back((Q){x,y,i});
            }
        }
        for(k=1;k<=cnth;k++){
            int now=0;
            P* h1=e1[k].data();
            Q* h2=e2[k].data();
            for(int i=0;i<e2[k].size();i++){
                while(now<e1[k].size()&&h1[now].T<=h2[i].T){
                    add(l[h1[now].x],h1[now].s);                
                    add(r[h1[now].x]+1,-h1[now].s);                
                    now++;
                }
                int id=h2[i].T;
                ans[id]+=query(pos[h2[i].l]); ans[id]+=query(pos[h2[i].r]);
                int lca=find(h2[i].l,h2[i].r),fa=f[lca][0];
                ans[id]-=query(pos[lca]); ans[id]-=query(pos[fa]);
            }
        }
        for(int i=1;i<=m;i++)if(mark[i]) printf("%d
    ",ans[i]);
        return 0;
    }
    View Code
  • 相关阅读:
    安卓之屏幕适配
    Kotlin入门教程——目录索引
    Kotlin入门(33)运用扩展属性
    Kotlin入门(32)网络接口访问
    Kotlin入门(31)JSON字符串的解析
    Kotlin入门(30)多线程交互
    Kotlin入门(29)任务Runnable
    Kotlin入门(28)Application单例化
    Kotlin入门(27)文件读写操作
    Kotlin入门(26)数据库ManagedSQLiteOpenHelper
  • 原文地址:https://www.cnblogs.com/lyzuikeai/p/7453837.html
Copyright © 2020-2023  润新知