C. lxs Contest #140Cac

Posted betablewaloot

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C. lxs Contest #140Cac相关的知识,希望对你有一定的参考价值。

【题意】

技术图片

技术图片

【题解】

仙人掌,考虑圆方树。

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

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

题目中修改操作即将两个圆点在新树上的路径上方点都加上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,因为维护他的方点没法加。

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

代码如下:

以上是关于C. lxs Contest #140Cac的主要内容,如果未能解决你的问题,请参考以下文章

floj 2265 lxs Contest #141航海舰队

Codeforces Round #604 (Div. 2) C. Beautiful Regional Contest

2019-2020 ICPC, Asia Jakarta Regional Contest C. Even Path

Dwango Programming Contest 6th Task C. Cookie Distribution

AtCoder NIKKEI Programming Contest 2019 C. Different Strokes (贪心)

2019 GDUT Rating Contest III : Problem C. Team Tic Tac Toe