Comet OJ - Contest # 11 D isaster reconstructed tree multiplier + + + DFS sequence segment tree

It found that for any one side, play a decisive role in the greater number of node points. 

Thus, for each side, in accordance with the node number larger value as the edge weight, based on the minimum spanning tree can be inserted manner. 

Last modification dfs sequence with a segment tree to make a range query. 

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\n"); 
            else 
            {  
                int k=get(x,y);    
                int L=st[k], R=ed[k];   
                printf("%lld\n",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;     
} 

  

Guess you like

Origin www.cnblogs.com/guangheli/p/11570836.html