zoukankan      html  css  js  c++  java
  • 【CF487E】Tourists

    题面   

    https://www.luogu.org/problemnew/show/CF487E

    1、$LCT$ 中,翻转懒标记,我是在打上的一刻同时进行翻转左右儿子,所以在 $makeroot(x)$ 的时候 $rev[x] oplus =1,swap(ch[x][0],ch[x][1])$

    2、$LCT$ 中,处理子树信息时(此题没有涉及到),$makeroot(x)$ 即变成以x为根的有根树。(虽然这是$makeroot$真实的含义,但我还是觉得好神奇)

    3、$LCT$ 中,初始化,每个节点形成一个子树,记得把节点维护的信息加进去。

    4、$Tarjan(x)$时,判定点双的方程是$low[y]>=dfn[x]$,弹栈时把$y$弹出为止,并且把$x$连上去。

    5、圆方树,有根化的小$trick$。

    6、$mutiset$,删除相同的只删除一个。(所以此题才能放心删)

    7、记一下结论吧,防止以后忘了。

    • $rotate(x)$  6(2判)+2;
    • $splay(x)$ 遍历同一棵splay上的祖先+1特判+两种情况
    • $access(x)$ 1+2+2
    • $makeroot(x)$ 2+2+1
    • $link(x)$ 2
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<set>
    #include<vector>
    #include<stack>
    #define ri register int
    #define N 405000
    using namespace std;
    
    int read() {
      int ret=0,f=0; char ch=getchar();
      while (ch<'0' || ch>'9') f|=(ch=='-'),ch=getchar();
      while (ch>='0' && ch<='9') ret=ret*10+(ch-'0'),ch=getchar();
      return f?-ret:ret;
    }
    int tn,n,m,q;
    int w[N];
    
    struct tree {
      vector<int> to[N];
      int fa[N],d[N],f[N][20];
      multiset<int> s[N];
      void add_edge(int u,int v) {
        to[u].push_back(v); 
        to[v].push_back(u);
      }
      void maketree(int x,int ff) {
        d[x]=d[ff]+1;
        f[x][0]=fa[x]=ff;
        for (ri i=1;i<=18;i++) f[x][i]=f[f[x][i-1]][i-1];
        for (ri i=0;i<to[x].size();i++) {
          int y=to[x][i];
          if (y==ff) continue;
          maketree(y,x);
        }
      }
      int lca(int u,int v) {
        if (d[u]<d[v]) swap(u,v);
        for (ri i=18;i>=0;i--) if (d[f[u][i]]>=d[v]) u=f[u][i];
        if (u==v) return u;
        for (ri i=18;i>=0;i--) if (f[u][i]!=f[v][i]) u=f[u][i],v=f[v][i];
        return fa[u];
      }
      void init(int x) {
        for (ri i=0;i<to[x].size();i++) {
          int y=to[x][i];
          if (y==fa[x]) continue;
          s[x].insert(w[y]);
        }
        w[x]=*(s[x].begin());
      }
    } T;
    
    struct link_cut_tree {
      bool rev[N];
      int fa[N],poi[N];
      int ch[N][2];
        
      inline bool notroot(int x) {
        return ch[fa[x]][0]==x || ch[fa[x]][1]==x;
      }
      inline bool opt(int x) {
        return (ch[fa[x]][1]==x);
      }
      void pushup(int x) {
        poi[x]=x;
        if (ch[x][0] && w[poi[ch[x][0]]]<w[poi[x]]) poi[x]=poi[ch[x][0]];
        if (ch[x][1] && w[poi[ch[x][1]]]<w[poi[x]]) poi[x]=poi[ch[x][1]];
      }
      void pushr(int x) {
        if (!rev[x] || !x) return;
        rev[x]=0;
        if (ch[x][0]) swap(ch[ch[x][0]][0],ch[ch[x][0]][1]),rev[ch[x][0]]^=1;
        if (ch[x][1]) swap(ch[ch[x][1]][0],ch[ch[x][1]][1]),rev[ch[x][1]]^=1;
      }
    
      void rotate(int x) {
        int y=fa[x],z=fa[y],s=opt(x),w=ch[x][1^s];
        fa[x]=z; if (notroot(y)) ch[z][opt(y)]=x;
        if (w) fa[w]=y; ch[y][s]=w;
        fa[y]=x; ch[x][1^s]=y;
        pushup(y); pushup(x);
      }
    
      void splay(int x) {
        int y=x;
        stack<int> stk; while (!stk.empty()) stk.pop();
        while (notroot(y)) stk.push(y),y=fa[y]; stk.push(y);
        while (!stk.empty()) pushr(stk.top()),stk.pop();
        while (notroot(x)) {
          int y=fa[x];
          if (!notroot(y)) rotate(x);
          else if (opt(x)==opt(y)) rotate(y),rotate(x); else rotate(x),rotate(x);
        }
      }
    
      void access(int x) {
        int y=0;
        while (x) {
          splay(x);
          ch[x][1]=y; pushup(x);
          y=x; x=fa[x];
        }
      }
    
      void makeroot(int x) {
        access(x); splay(x);
        rev[x]^=1; swap(ch[x][0],ch[x][1]);
        pushr(x);
      }
    
      void link(int u,int v) {
        makeroot(u);
        fa[u]=v;
      }
        
    } lct;
    
    struct graph {
      vector<int> to[N];
      stack<int> stk;
      int tot;
      int dfn[N],low[N];
      void add_edge(int u,int v) {
        to[u].push_back(v);
        to[v].push_back(u);
      }
      void tarjan(int x) {
        dfn[x]=low[x]=++tot;
        stk.push(x);
        for (ri i=0;i<to[x].size();i++) {
          int y=to[x][i];
          if (dfn[y]) {
            low[x]=min(low[x],dfn[y]);
          }
          else {
            tarjan(y);
            low[x]=min(low[y],low[x]);
            if (low[y]>=dfn[x]) {
              ++n; int t;
              do {
                t=stk.top(); stk.pop();
                T.add_edge(n,t);
              }
              while (t!=y);
              T.add_edge(n,x);
            }
          }
        }
      }
    } G;
    
    void change(int x,int v) {
      int y=T.fa[x];
      T.s[y].erase(w[x]);
      lct.splay(x);
      w[x]=v;
      T.s[y].insert(w[x]);
      lct.splay(y);
      w[y]=*(T.s[y].begin());
    }
    
    int query(int x,int y) {
      lct.makeroot(x);
      lct.access(y);
      lct.splay(y);
      int z=T.lca(x,y);
      if (z>tn) return min(w[lct.poi[y]],w[T.fa[z]]);
      return w[lct.poi[y]];
    }
    
    int main(){
      char opt[10];
      tn=n=read(); m=read(); q=read();
      memset(w,0x3f,sizeof(w));
      for (ri i=1;i<=n;i++) w[i]=read();
      for (ri i=1;i<=m;i++) {
        int u=read(),v=read();
        G.add_edge(u,v);
      }
      G.tot=0; G.tarjan(1);
      T.maketree(1,1);
      for (ri i=1;i<=n;i++) {
        lct.poi[i]=i;
        if (T.fa[i]!=i) lct.link(T.fa[i],i);
        if (i>tn) T.init(i);
      }
      for (ri i=1;i<=q;i++) {
        scanf("%s",opt);
        int u=read(),v=read();
        if (opt[0]=='A') printf("%d
    ",query(u,v));
        else if (opt[0]=='C') change(u,v);
      }
      return 0;
    }
  • 相关阅读:
    【转】最奇特的编程语言特征
    【原】mysql 视图
    自己动手写ORM框架(一):目标效果预览
    (二)Javascript面向对象:命名空间
    在JAVA中封装JSONUtils工具类及使用(一)
    .NET3.5中JSON用法以及封装JsonUtils工具类(二)
    (四)Javascript面向对象:继承
    自己动手写ORM框架(三):关系映射配置—Table属性
    (一)javascript面向对象:(2)类
    自己动手写ORM框架(二):AdoHelper支持多数据库操作的封装(1)
  • 原文地址:https://www.cnblogs.com/shxnb666/p/11074404.html
Copyright © 2011-2022 走看看