• 列队题解以及注意事项


    一道十分interesting的题目

    这道题显然要使用数据结构维护。但是n的规模十分大。我们便可以开n棵线段树,动态开点。但是最后一列比较特殊,所以我们再开一棵线段树维护最后一列。至于怎么操作?我们考虑权值线段树。权值线段树一般是维护:权值为[L,r]的数有多少是满足某种条件的。本道题目中我们维护区间[L,R]中有多少个数没有操作过。线段树的长度要开为 max(n,m)+q,这样如果我们查询一个数的位置发现她超过了m,说明她已经不在原位置了,出去的数我们用vector存储,每次直接访问下标就可以查询了。这里的原理就是查询该行排名为k的点。发现这个点之后就将其压入维护最后一列的vector中,并将此时在最后一列中排名为K的点压入改行,就行了。注意特判询问的纵坐标为m的情况

    code:

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #include<algorithm>
    #include<cmath>
    #include<set>
    #include<cstring>
    #include<vector> 
    #define max MAX
    #define maxn 5000006
    #define mod 1000000007
    #define rep(i,a,b) for (int i=a;i<=b;++i)
    #define erep(i,a) for (int i=head[a];i!=-1;i=e[i].next)
    #define half (l+r)>>1
    #define lson t[s].lc
    #define pb push_back
    #define all (zmd)
    #define rson t[s].rc
    using namespace std;
    #define int long long 
    
    struct zmd
    {
        int fx,fy;	
    };
    struct hzw
    {
        int lc,rc,sum;
    }t[maxn]; 
    int n,m,mx,tot,q;
    inline int MAX(int a,int b) {return a>b?a:b;}
    inline void update(int &s,int l,int r,int p)
    {
        if (!s) s=++tot;
        if (l==r)
        {
            t[s].sum++;
            return;	
        } 
        int mid=half;
        if (p<=mid) update(lson,l,mid,p);
        else update(rson,mid+1,r,p);
        t[s].sum=t[lson].sum+t[rson].sum;
    }
    int root[maxn];
    inline int query(int s,int l,int r,int p)
    {
        if (l==r) return l;
        int mid = half;
        int tmp=(mid-l+1) - t[lson].sum;
        if (p<=tmp) return query(lson,l,mid,p);
        else return query(rson,mid+1,r,p-tmp);
    }
    vector<zmd>v[300006];
    inline int solve1(int x,int y)
    {
        int now = query(root[x],1,mx,y),ans;
        update(root[x],1,mx,now); // take away
        if (now<m) 
        {
            ans=m*(x-1)+now; 
            v[n+1].pb(all{x,now}); //insert back
        }
        else 
        {
            zmd wow = v[x][now-m];
            ans=m*(wow.fx-1)+wow.fy;
            v[n+1].pb(wow);
        }	
        int bk = query(root[n+1],1,mx,x);
        update(root[n+1],1,mx,bk);
        if (bk<=n) v[x].pb(all{bk,m}); //no used is insert easily
        else {zmd wow = v[n+1][bk-n-1];v[x].pb(wow);} //find and insert now    
        return ans;   
    }
    inline int solve2(int x,int y)  // final insert
    {
        int now=query(root[n+1],1,mx,x);
        update(root[n+1],1,mx,now);
        zmd wow;
        if (now<=n) wow.fx=now,wow.fy=m;
        else wow = v[n+1][now-n-1];
        v[n+1].pb(wow);  
        return m*(wow.fx-1)+wow.fy;
    }
    #undef int
    int main()
    {
        #define int long long 
        cin>>n>>m>>q;
        mx = max(n,m)+q;
        rep(i,1,q)
        {
            int a,b;
            scanf("%lld%lld",&a,&b);
            printf("%lld
    ",b==m?solve2(a,b):solve1(a,b));
        }
        return 0;
    }
    

    注意事项:

    define max(a,b) a>b?a:b 有时候会出玄学错误:例子:

    看,十分玄妙,所以不要乱define了

  • 相关阅读:
    CSS3学习手记(7) CSS3装换 3D转换
    CSS3学习手记(6) CSS3装换 2D转换
    CSS3学习手记(5) 渐变
    CSS3学习手记(4) 伪元素
    CSS3学习手记(3) CSS权重
    CSS3学习手记(2) 伪类选择器
    CSS3学习手记(1) 选择器
    HTML5学习手记(二)
    HTML5学习手记(一)
    浏览器远程调试VS
  • 原文地址:https://www.cnblogs.com/bullshit/p/9890386.html
Copyright © 2020-2023  润新知