zoukankan      html  css  js  c++  java
  • C. 【lxs Contest #140】Cac

    【题意】

    【题解】

    仙人掌,考虑圆方树。

    正常构建圆方树并在每两个树边之间加入方点。

    考虑使用每个方点维护与他相连的圆点信息,发现每个方点只能维护他的儿子圆点信息,否则会算重。

    题目中修改操作即将两个圆点在新树上的路径上方点都加上v,即表示路径上所有环上的圆点都加v。

    #include<bits/stdc++.h>
    #define int long long
    using namespace std;
    const int N=6e5+5;
    const int mo=998244353;
    int n,m,q,last[N],size,dfn[N],low[N],siz,dui[N],ans[N],size1,last1[N],dax[N],f[N][20],len,cnt,st[N],toptop,Dfn[N],gaga;
    struct pigu
    {
        int dao,ne;
    }a[N<<3],b[N<<2];
    inline void lingjiebiao(int x,int y)
    {
        a[++size].dao=y;
        a[size].ne=last[x];
        last[x]=size;
    }
    inline void lingjiebiao2(int x,int y)
    {
        b[++size1].dao=y;
        b[size1].ne=last1[x];
        last1[x]=size1;
    }
    inline int jia(int x,int y)
    {
        return (((x+y)%mo)+mo)%mo;
    }
    inline int read()
    {
        char c=getchar();
        int x=0,f=1;
        while(!isdigit(c)) {if(c=='-') f=-1;c=getchar();}
        while(isdigit(c)) {x=(x<<3)+(x<<1)+c-'0';c=getchar();}
        return x*f; 
    }
    inline void tarjan(int now,int fa)
    {
        dfn[now]=low[now]=++cnt;
        st[++toptop]=now;
        for(int i=last[now];i;i=a[i].ne)
        {
            if(dfn[a[i].dao]==0)
            {
                tarjan(a[i].dao,now);
                low[now]=min(low[now],low[a[i].dao]);
                if(low[a[i].dao]==dfn[now])
                {
                    int k;
                    ++siz;
                    do
                    {
                        k=st[toptop--];
                        lingjiebiao2(k,siz);
                        lingjiebiao2(siz,k);
                    }while(k!=a[i].dao);
                    lingjiebiao2(now,siz);
                    lingjiebiao2(siz,now); 
                }
            }
            else
                low[now]=min(low[now],dfn[a[i].dao]);
        }
    }
    int dep[N],sh[N],Siz[N];
    inline int lowbit(int x)
    {
        return x&(-x);
    }
    inline void modify(int zai,int zhi)
    {
        for(int i=zai;i<=siz;i+=lowbit(i)) sh[i]=jia(sh[i],zhi);
    }
    inline int dquery(int x)
    {
        int ha=0;
        for(int i=x;i;i-=lowbit(i)) ha=jia(ha,sh[i]);
        return ha;
    }
    inline int query(int x)
    {
        return dquery(Dfn[x]+Siz[x]-1)-dquery(Dfn[x]-1)+mo;
    }
    inline void dfs(int now,int fa)
    {
        f[now][0]=fa;dep[now]=dep[fa]+1;Dfn[now]=++gaga;Siz[now]=1;
        for(int i=1;f[f[now][i-1]][i-1];i++) f[now][i]=f[f[now][i-1]][i-1];
        for(int i=last1[now];i;i=b[i].ne)
        {
            if(b[i].dao==fa) continue;
            dfs(b[i].dao,now);
            Siz[now]+=Siz[b[i].dao];
        }
    }
    inline int get_lca(int x,int y)
    {
        if(dep[x]<dep[y]) swap(x,y);
        for(int i=19;i>=0;i--) if(dep[f[x][i]]>=dep[y]) x=f[x][i];
        if(x==y) return x;
        for(int i=19;i>=0;i--) if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
        return f[x][0];
    }
    signed main()
    {
    //    freopen("cac.in","r",stdin);
        //freopen("cac.out","w",stdout);
        n=read();m=read();q=read();
        for(int i=1,x,y;i<=m;i++)
        {
            x=read();y=read();
            lingjiebiao(x,y);
            lingjiebiao(y,x);
        }siz=n;
        tarjan(1,0);
        dfs(1,0);
        for(int i=1,x,y,z,v;i<=q;i++)
        {
            x=read();y=read();
            if(x==0)
            {
                z=read();v=read();
                int lca=get_lca(y,z);
                modify(Dfn[y],v);
                modify(Dfn[z],v);
                modify(Dfn[lca],mo-v);
                if(f[lca][0]) modify(Dfn[f[lca][0]],mo-v);
                if(lca>n) ans[f[lca][0]]=jia(ans[f[lca][0]],v);
                else ans[lca]=jia(ans[lca],v);
            }
            else
            {
                int daan=jia(ans[y],f[y][0]?query(f[y][0]):0);
                cout<<daan<<"
    ";
            }
        }
    }
    View Code

    注意如果lca是圆点,则需将该圆点答案单独加上v,因为维护他的方点没法加。

    查询即查询该点本身及他的父亲方点的权值即可,使用树链剖分或树上差分即可。

    代码如下:

  • 相关阅读:
    USACOZero Sum
    USACOControlling Companies
    USACOParty Lamps
    USACOMoney Systems
    UVa11292
    USACOLongest Prefix
    USACOThe Tamworth Two
    USACORunaround Numbers
    业内常见电子病历编辑器简单比较(1)编辑控件来源比较
    GB(国标)字典大全
  • 原文地址:https://www.cnblogs.com/betablewaloot/p/12210697.html
Copyright © 2011-2022 走看看