• [PA2014]Fiolki


    https://zybuluo.com/ysner/note/1228184

    题面

    吉丽有(n)种不同的液体物质,和(n)个药瓶(均从1到n编号)。吉丽需要执行一定的(k)步骤来配置药水,步骤是将某个瓶子内的所有液体倒入另一个瓶子。
    吉丽知道某(m)对液体物质在一起时会发生反应产生沉淀。生成的沉淀不会和任何物质反应。当有多于一对可以发生反应的物质在一起时,吉丽知道它们的反应顺序。每次倾倒完后,吉丽会等到反应结束后再执行下一步骤。吉丽想知道配置过程中总共产生多少沉淀。

    • (m,nleq2*10^5,kleq5*10^5)

    解析

    这题真是脑洞神题
    发现模拟妥妥的(O(mk))
    记得约束关系一般都能牵扯到图论。(然后我就懵了
    实际上,这种化学反应(化合反应)很容易让我们想起树形结构

    于是一切都自然了。
    我们把生成物作为一对反应物的父亲,反应完就把反应物的位置改到生成物那儿。
    这样能构成森林。(图不一定联通
    显然深度越大,反应顺序越靠前的越先反应。
    按此顺序,通过找(lca)得到生成物,一一模拟即可。
    复杂度(O(klogn))

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #define re register
    #define il inline
    #define ll long long
    #define max(a,b) ((a)>(b)?(a):(b))
    #define min(a,b) ((a)<(b)?(a):(b))
    #define fp(i,a,b) for(re int i=a;i<=b;i++)
    #define fq(i,a,b) for(re int i=a;i>=b;i--)
    using namespace std;
    const int N=5e5+100;
    struct Edge{int to,nxt;}e[N<<1];
    struct dat{int u,v,lca,deep,id;bool operator < (const dat &o) const{return (deep>o.deep)||(deep==o.deep&&id<o.id);}}a[N<<1];
    int n,g[N],tot,m,k,cnt,h[N],ff,d[N],sz[N],son[N],f[N],top[N],pos[N];
    ll ans;
    il void add(re int u,re int v){e[++cnt]=(Edge){v,h[u]};h[u]=cnt;e[++cnt]=(Edge){u,h[v]};h[v]=cnt;}
    il ll gi()
    {
      re ll x=0,t=1;
      re char ch=getchar();
      while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
      if(ch=='-') t=-1,ch=getchar();
      while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
      return x*t;
    }
    il void dfs1(re int u,re int fa)
    {
      d[u]=d[fa]+1;f[u]=fa;sz[u]=1;
      for(re int i=h[u];i+1;i=e[i].nxt)
        {
          re int v=e[i].to;
          if(v==fa) continue;
          dfs1(v,u);
          sz[u]+=sz[v];
          if(sz[son[u]]<sz[v]) son[u]=v;
        }
    }
    il void dfs2(re int u,re int up)
    {
      top[u]=up;
      if(son[u]) dfs2(son[u],up);
      for(re int i=h[u];i+1;i=e[i].nxt)
        {
          re int v=e[i].to;
          if(v==f[u]||v==son[u]) continue;
          dfs2(v,v);
        }
    }
    il int getlca(re int u,re int v)
    {
      while(top[u]^top[v])
        {
          if(d[top[u]]<d[top[v]]) swap(u,v);
          u=f[top[u]];
        }
      return d[u]<d[v]?u:v;
    }
    int main()
    {
      memset(h,-1,sizeof(h));
      n=gi();m=gi();k=gi();
      fp(i,1,n) pos[i]=i,g[i]=gi();
      fp(i,1,m)
        {
          re int u=gi(),v=gi(),ff=n+i;
          add(pos[u],ff);add(pos[v],ff);pos[v]=ff;
        }
      fq(i,n+m,1) if(!f[i]) dfs1(i,0),dfs2(i,i);
      fp(i,1,k)
      {
        re int u=gi(),v=gi(),lca=getlca(u,v);
        if(!lca) continue;//不反应
        a[++tot]=(dat){u,v,lca,d[lca],i};
      }
      sort(a+1,a+1+tot);
      fp(i,1,tot)
        {
          re int u=a[i].u,v=a[i].v,gg=min(g[u],g[v]);
          g[u]-=gg;g[v]-=gg;ans+=gg*2;
        }
        printf("%lld
    ",ans);
      return 0;
    }
    
  • 相关阅读:
    centos下使用yum 安装pip
    什么叫对象引用对象
    变量,id()
    语法错误
    闭包,装饰器
    位运算&,逻辑与and
    for XX in XX结构
    Python中的部分特殊属性
    利用键盘实现橡皮筋技术
    hdu Random Sequence
  • 原文地址:https://www.cnblogs.com/yanshannan/p/9375209.html
Copyright © 2020-2023  润新知