zoukankan      html  css  js  c++  java
  • [noip2017]列队

    https://www.zybuluo.com/ysner/note/1322438

    题面

    无人不知,无人不晓

    解析

    想想如何简化题目中的操作。
    一个人到((n,m)),暴力模拟的复杂度是(O(n+m))
    考虑节省掉移动整行整列的复杂度。

    实际上,不如让一个人移走后留下的位置空着。
    这样一行最多只有(6*10^5),是可以维护的。

    于是用(n)棵线段树维护一下每一行中,区间内有多少个空位置。
    这样就可以查出一行的第(k)个在哪里。

    当然,如果每行线段树都开全,空间复杂度(O(nm))开不下。
    所以需要动态开点。

    注意到只有(n)行和第(m)列有可能新加入数。
    可以用(vector)存一下,每行新加入了什么数(第(m)列不包含在内)。
    还有一个(vector)存第(m)列新加入的数。

    另外,删掉(vector)中的数也是(O(n))级别的。所以每行的线段树也要维护(vector)中的空位置。

    这么以来,操作就转化为在数据结构的基础上模拟了。

    #include<iostream>
    #include<cmath>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #define ll long long
    #define re register
    #define il inline
    #define pb push_back
    #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=3e5+100;
    int n,m,q,t[N*100],tot,rt[N*100],tim,ls[N*100],rs[N*100];
    vector<ll>V[N];
    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 Inherit(re int &x)
    {
      rt[++tim]=rt[x];t[tim]=t[x];ls[tim]=ls[x];rs[tim]=rs[x];x=tim;
    }
    il int Query(re int &x,re int l,re int r,re int k)
    {
      Inherit(x);
      if(l==r) {t[x]=1;return l;}
      re int mid=l+r>>1,sz=mid-l+1-t[ls[x]],ans;
      if(k<=sz) ans=Query(ls[x],l,mid,k);
      else ans=Query(rs[x],mid+1,r,k-sz);
      t[x]=t[ls[x]]+t[rs[x]];
      return ans;
    }
    il ll find(re int i,re int k)
    {
      re ll ans=Query(rt[i],1,tot,k),l=(i<=n?m-1:n);
      if(ans<=l) return i<=n?1ll*(i-1)*m+ans:ans*m;
      else return V[i][ans-l-1];
    }
    int main()
    {
      n=gi();m=gi();q=gi();tot=max(n,m)+q;
      fp(i,1,n+1) rt[i]=++tim;
      fp(i,1,q)
        {
          re int x=gi(),y=gi();re ll p1,p2;
          if(y^m)
        {
          p1=find(x,y);V[n+1].pb(p1);//a new member on lie m
          p2=find(n+1,x);V[x].pb(p2);//new one ->the n_th line
        }
          else p1=find(n+1,x),V[n+1].pb(p1);
          printf("%lld
    ",p1);
        }
      return 0;
    }
    
  • 相关阅读:
    屏蔽右键
    无法解析类型 java.lang.Object。从必需的 .class 文件间接引用了它
    屏蔽右键
    Servlet的三个基本方法
    应用HttpClient来对付各种顽固的WEB服务器 摘抄
    Apache xmlrpc
    利用缓存机制快速读取XML文件数据
    JDBC连接MySQL
    HttpClient入门
    5款主流NoSQL数据库全方位横评
  • 原文地址:https://www.cnblogs.com/yanshannan/p/9852938.html
Copyright © 2011-2022 走看看