zoukankan      html  css  js  c++  java
  • 洛谷T31018 经典题丶改(LCT+离线)

    真的是一个大好题啊!

    QWQ首先我们考虑这种问题,如果直接在线做,估计应该是做不了,那我们是不是可以直接考虑离线。

    将所有询问都按照(r)来排序。

    然后依次加入每条边,计算(a[i]<=nowr)的答案

    离线下来之后呢。

    我们对于依次加入的边,实际上就相当于一个维护生成树的过程,那么qwq应该以什么为关键字呢?

    由于我们可以精妙的发现,对于(r)不减(或者说不变)来说,编号小的边总是比大的边要没用,因为既然([l+x,r])能使联通的话,那么([l,r])也一定可以。

    我们令每条边的边权是他的编号

    那么我们维护的就是一个最小边权最大的生成树

    然后类似(two pointer)

    对于每一个(i),我们都暴力把(r<=i)的指针++,然后看一下是否联通,联通的条件是(findroot(x)==findroot(y) 且 mn[y]>=l),后面这项表示(x->y)的路径上最小的编号,要在他要求的(l)之后才行。

    QWQ嘤嘤嘤
    还有一个问题一定要注意!!!
    就是点的编号的问题。

    我们一定要强制让每个边对应的点的编号是(i+n),不要忽略重边和自环(如果你是用一个(tot)记录的话)

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<map>
    #include<set>
    #define mk makr_pair
    #define ll long long
    using namespace std;
    inline int read()
    {
      int x=0,f=1;char ch=getchar();
      while (!isdigit(ch)) {if (ch=='-') f=-1;ch=getchar();}
      while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
      return x*f;
    }
    const int maxn = 5e5+1e2;
    const int maxm = maxn;
    struct Node{
     int l,r,a,b,id;
    };
    Node a[maxn];
    int ch[maxn][3];
    int rev[maxn],fa[maxn];
    int n,m,cnt;
    int mn[maxn],mnpos[maxn];
    int val[maxn];
    int xx[maxm],yy[maxm];
    int ans[maxn];
    int k;
    int son(int x)
    {
     if (ch[fa[x]][0]==x) return 0;
     else return 1;
    }
    bool notroot(int x)
    {
     if(!x) return 0; 
     return ch[fa[x]][0]==x || ch[fa[x]][1]==x;
    }
    void update(int x) 
    {
     if (!x) return;
     mn[x]=val[x];
     mnpos[x]=x;
     if (ch[x][0])
     {
      if (mn[x]>mn[ch[x][0]])
      {
       mn[x]=mn[ch[x][0]];
       mnpos[x]=mnpos[ch[x][0]];
      }
     }
     if (ch[x][1])
     {
      if(mn[x]>mn[ch[x][1]])
      {
       mn[x]=mn[ch[x][1]];
       mnpos[x]=mnpos[ch[x][1]];
      }
     }
    }
    void reverse(int x)
    {
     swap(ch[x][0],ch[x][1]);
     rev[x]^=1;
    }
    void pushdown(int x)
    {
     if(rev[x])
     {
      if (ch[x][0]) reverse(ch[x][0]);
      if (ch[x][1]) reverse(ch[x][1]);
      rev[x]=0;
     }
    }
    void rotate(int x)
    {
     int y=fa[x],z=fa[y];
     int b=son(x),c=son(y);
     if (notroot(y)) ch[z][c]=x;
     fa[x]=z;
     ch[y][b]=ch[x][!b];
     fa[ch[x][!b]]=y;
     ch[x][!b]=y;
     fa[y]=x;
     update(y);
     update(x);
    }
    int st[maxn];
    void splay(int x)
    {
     int y=x,cnt=0;
     st[++cnt]=y;
     while (notroot(y)) y=fa[y],st[++cnt]=y;
     while (cnt) pushdown(st[cnt--]);
     while (notroot(x))
     {
      int y=fa[x],z=fa[y];
      int b=son(x),c=son(y);
      if (notroot(y))
      {
       if(b==c) rotate(y);
       else rotate(x); 
       } 
       rotate(x);
     }
     update(x); 
    }
    void access(int x)
    {
     for (int y=0;x;y=x,x=fa[x])
     {
      splay(x);
         ch[x][1]=y;
         update(x);
     }
    }
    void makeroot(int x)
    {
     access(x);
     splay(x);
     reverse(x);
    }
    int findroot(int x)
    { 
     access(x);
     splay(x);
     while (ch[x][0])
     {
      pushdown(x);
      x=ch[x][0];
        }
       // cout<<x<<endl; 
     return x;
    }
    void split(int x,int y)
    {
     makeroot(x);
     access(y);
     splay(y);
    }
    void link(int x,int y)
    {
     makeroot(x);
     if (findroot(y)!=x)
     {
      fa[x]=y;
     }
    }
    void cut(int x,int y)
    {
     split(x,y);
     if (ch[x][0] || ch[x][1] || fa[x]!=y || ch[y][1]) return;
     fa[x]=ch[y][0]=0;
     update(y);
    }
    bool cmp(Node a,Node b)
    {
     return a.r<b.r;
    }
    int main()
    {
      val[0]=1e9;
      n=read(),m=read(),k=read();
      for (int i=1;i<=n;i++) val[i]=1e9;
      for (int i=1;i<=m;i++) xx[i]=read(),yy[i]=read();
      for (int i=1;i<=k;i++)
      {
        a[i].l=read();
        a[i].r=read();
        a[i].a=read();
      a[i].b=read();
      a[i].id=i; 
      }
      sort(a+1,a+1+k,cmp);
      int tot=n;
      int now=1;
      for (int i=1;i<=m && now<=k;i++)
      {
        int x = xx[i],y=yy[i];
        //int rr = a[now].r
      ++tot;
      val[tot]=i;
        if(x!=y)
        {
         split(x,y);
         if (x!=findroot(y))
         {
          link(x,tot);
          //cout<<1<<endl;
          link(y,tot);
      }
      else
      {
       int nnow = mnpos[y];
       cut(xx[nnow-n],nnow);
       cut(yy[nnow-n],nnow);
       link(x,tot);
       link(y,tot);
      }
      }
      while (now<=k && a[now].r<=i)
      {
        if (a[now].a==a[now].b) ans[a[now].id]=1;
        else 
        {
          split(a[now].a,a[now].b);
         if (a[now].a==findroot(a[now].b))
       {
        // cout<<a[now].a<<" "<<a[now].b<<" "<<mn[a[now].b]<<endl;
         if (mn[a[now].b]>=a[now].l) ans[a[now].id]=1;
       }
       }
       now++;
       }
     // cout<<findroot(1)<<" "<<findroot(3)<<endl;
      }
      for (int i=1;i<=k;i++)
      {
        if (ans[i])
        {
         cout<<"ye5
    "; 
      }
      else cout<<"n0
    ";
      }
      return 0;
    }
    
  • 相关阅读:
    bzoj2819: Nim
    bzoj4864: [BeiJing 2017 Wc]神秘物质
    【转】 随机梯度下降(Stochastic gradient descent)和 批量梯度下降(Batch gradient descent )的公式对比、实现对比
    【转】梯度下降算法原理
    梯度下降算法的一点认识(Ng第一课)
    快速理解webStroage
    Css选择器实例
    Canvas实例
    HTML5中的Canvas
    骰子效果实例
  • 原文地址:https://www.cnblogs.com/yimmortal/p/10161939.html
Copyright © 2011-2022 走看看