• Comet OJ


    发现对于任意一条边,起决定性作用的是节点编号更大的点. 

    于是,对于每一条边,按照节点编号较大值作为边权,按照最小生成树的方式插入即可. 

    最后用线段树维护 dfs 序做一个区间查询即可. 

    Code: 

    #include <bits/stdc++.h> 
    #define N 400005   
    #define ll long long 
    #define mod 998244353    
    #define setIO(s) freopen(s".in","r",stdin) 
    using namespace std;             
    ll val[N],mul[N<<2],V[N];        
    int n,m,Q,tot,edges,tt;    
    int p[N],cc[N],hd[N],to[N],nex[N],dfn[N],st[N],ed[N],size[N],Fa[21][N],F[21][N];   
    struct Edge 
    {
        int u,v,c; 
        Edge(int u=0,int v=0,int c=0):u(u),v(v),c(c){}  
    }e[N];                                                      
    void pushup(int l,int r,int now) 
    { 
        ll re=1;  
        int mid=(l+r)>>1;   
        if(l<=mid)re=re*mul[now<<1]%mod;   
        if(r>mid) re=re*mul[now<<1|1]%mod;         
        mul[now]=re;     
    }
    void build(int l,int r,int now) 
    {
        if(l==r) 
        {
            mul[now]=V[l]%mod;        
            return;   
        } 
        int mid=(l+r)>>1;  
        if(l<=mid) build(l,mid,now<<1);   
        if(r>mid)  build(mid+1,r,now<<1|1);    
        pushup(l,r,now);         
    }
    void update(int l,int r,int now,int p,int v) 
    {
        if(l==r) 
        {
            V[l]=mul[now]=1ll*v%mod;  
            return;   
        }  
        int mid=(l+r)>>1;      
        if(p<=mid) update(l,mid,now<<1,p,v);  
        else update(mid+1,r,now<<1|1,p,v);  
        pushup(l,r,now);       
    }
    ll query(int l,int r,int now,int L,int R) 
    {
        if(l>=L&&r<=R) return mul[now]; 
        ll re=1;   
        int mid=(l+r)>>1;     
        if(L<=mid) re=re*query(l,mid,now<<1,L,R)%mod;   
        if(R>mid)  re=re*query(mid+1,r,now<<1|1,L,R)%mod;  
        return re;    
    }
    int find(int x) 
    {
        return p[x]==x?x:p[x]=find(p[x]);   
    } 
    bool cmp(Edge a,Edge b) 
    {
        return a.c<b.c;     
    } 
    void addedge(int u,int v) 
    {
        nex[++edges]=hd[u],hd[u]=edges,to[edges]=v;     
    }
    void dfs(int u,int ff) 
    {
        st[u]=dfn[u]=++tt, size[u]=1, V[dfn[u]]=val[u];             
        Fa[0][u]=ff, F[0][u]=max(cc[ff], cc[u]);                
        for(int i=1;i<=20;++i) 
        {
            Fa[i][u]=Fa[i-1][Fa[i-1][u]]; 
            F[i][u]=max(F[i-1][u], F[i-1][Fa[i-1][u]]);     
        }
        for(int i=hd[u];i;i=nex[i]) 
        {    
            int v=to[i];   
            dfs(v, u);              
            size[u]+=size[v];   
        }    
        ed[u]=tt;   
    }
    int get(int x,int k) 
    {
        for(int i=20;i>=0;--i)     
            if(Fa[i][x] && F[i][x] <= k) x=Fa[i][x];    
        return x;      
    }
    int main() 
    {  
        int i,j,k; 
        // setIO("input"); 
        scanf("%d%d%d",&n,&m,&Q);
        tot=n;    
        for(i=1;i<N;++i) p[i]=i;   
        for(i=1;i<=n;++i) scanf("%lld",&val[i]),cc[i]=i;                  
        for(i=1;i<=m;++i)                     
        {
            scanf("%d%d",&e[i].u,&e[i].v);  
            e[i].c=max(e[i].u, e[i].v);   
        }
        sort(e+1,e+1+m,cmp);    
        for(i=1;i<=m;++i) 
        {             
            int u=e[i].u, v=e[i].v;   
            int x=find(u),y=find(v);   
            if(x!=y) 
            {
                ++tot;    
                val[tot]=1ll;   
                cc[tot]=e[i].c;    
                p[x]=tot,p[y]=tot;                                       
                addedge(tot,x), addedge(tot,y);     
            }
        }
        cc[0]=1000000000;    
        dfs(tot,0);
        build(1,tot,1);      
        for(i=1;i<=Q;++i) 
        {
            int op; 
            scanf("%d",&op);   
            if(op==1) 
            {
                int x,y; 
                scanf("%d%d",&x,&y);       
                if(x>y) printf("0
    "); 
                else 
                {  
                    int k=get(x,y);    
                    int L=st[k], R=ed[k];   
                    printf("%lld
    ",query(1,tot,1,L,R));  
                }
            }
            if(op==2) 
            {   
                int x,y; 
                scanf("%d%d",&x,&y);     
                update(1,tot,1,dfn[x],y);   
            }
        }   
        return 0;     
    } 
    

      

  • 相关阅读:
    读取Web.config文件中的配置信息类
    屏蔽页面中的右键操作
    树型目录
    自己常用的分页SQL
    c#用一个线程同步的简单例子

    c++面向对象学习
    数据上传项目总结
    简单的xml学习
    c#中跨线程使用控件
  • 原文地址:https://www.cnblogs.com/guangheli/p/11570836.html
Copyright © 2020-2023  润新知