码迷,mamicode.com
首页 > 其他好文 > 详细

NOIP2017 Day2 T3 列队(treap)

时间:2017-12-20 21:54:06      阅读:206      评论:0      收藏:0      [点我收藏+]

标签:read   poi   space   show   lap   ios   clu   void   color   

  可以直接用treap上大模拟...n+1个treap维护n行的前m-1个点和最后一列。

  需要支持删除一个点或者一段区间,而空间并不支持存下所有的点的时候,可以用一个点代替一个区间,记录区间首项的值和区间长度,这样每次查询某个点x的时候就可以用x在某个点y代表的区间里的rank来得到x的值,然后把x删去的时候,就把y这个区间从$[l,r]$拆分成$[l,x-1]$和$[x+1,r]$,重新加入。

  类似的题有NOI超级钢琴

技术分享图片
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#define ll long long
#define int long long
#define lt tree[x].ls
#define rt tree[x].rs
using namespace std;
const int maxn=6000010;
struct poi{ll beg; int rnd, size, ls, rs, len;}tree[maxn];
int n, m, Q, x, y, tott, tmp, rk;
ll ans;
int root[maxn], cnt[maxn], Len[maxn];
inline void read(int &k)
{
    int f=1; k=0; char c=getchar();
    while(c<0 || c>9) c==- && (f=-1), c=getchar();
    while(c<=9 && c>=0) k=k*10+c-0, c=getchar();
    k*=f;
}
inline void build(int &x, ll beg, int len)
{
    tree[x=++tott].beg=beg; tree[x].size=1; 
    tree[x].len=Len[x]=len;
    tree[x].rnd=rand()<<15|rand();
}
inline void up(int x) 
{
    tree[x].size=tree[lt].size+tree[rt].size+1; 
    tree[x].len=tree[lt].len+tree[rt].len+Len[x];
}
void split(int x, int &l, int &r, int k)
{
    if(!k) l=0, r=x;
    else if(tree[x].size==k) l=x, r=0;
    else if(tree[lt].size>=k) r=x, split(lt, l, lt, k), up(x);
    else l=x, split(rt, rt, r, k-tree[lt].size-1), up(x);
}
void rank(int x, int k)
{
    if(tree[lt].len<k && tree[lt].len+Len[x]>=k) ans=k-tree[lt].len, rk+=tree[lt].size+1;
    else if(k<=tree[lt].len) rank(lt, k);
    else rk+=tree[lt].size+1, rank(rt, k-tree[lt].len-Len[x]);
}
void merge(int &x, int l, int r)
{
    if(!l || !r) x=l+r;
    else if(tree[l].rnd<tree[r].rnd) x=l, merge(rt, rt, r), up(x);
    else x=r, merge(lt, l, lt), up(x);
}
inline void disc(int &Root, ll &poi, int pos)
{
    int x, y;
    rk=0; rank(Root, pos);
    split(Root, Root, y, rk); if(rk-1) split(Root, Root, x, rk-1); else x=Root;
    if(ans-1) build(tmp, tree[x].beg, ans-1), merge(Root, Root, tmp);
    if(Len[x]-ans) build(tmp, tree[x].beg+ans*(Root==root[n+1]?m:1), Len[x]-ans), merge(Root, Root, tmp);
    merge(Root, Root, y); poi=x; 
}
inline ll query(int posx, int posy)
{
    if(posy!=m)
    {
        ll ANS, poi;
        disc(root[posx], poi, posy); ANS=tree[poi].beg+ans-1;
        build(tmp, ANS, 1); merge(root[n+1], root[n+1], tmp);
        disc(root[n+1], poi, posx); poi=tree[poi].beg+(ans-1)*m; 
        build(tmp, poi, 1); merge(root[posx], root[posx], tmp);
        return ANS;
    }
    ll poi;
    disc(root[n+1], poi, posx); poi=tree[poi].beg+(ans-1)*m;
    build(tmp, poi, 1); merge(root[n+1], root[n+1], tmp);
    return poi;
}
#undef int
int main()
{
    srand(19260817);
    read(n); read(m); read(Q);
    for(int i=1;i<=n;i++) build(root[i], 1ll*1+(i-1)*m, m-1); build(root[n+1], m, n); 
    for(int i=1;i<=Q;i++) read(x), read(y), printf("%lld\n", query(x, y));
}
View Code

NOIP2017 Day2 T3 列队(treap)

标签:read   poi   space   show   lap   ios   clu   void   color   

原文地址:http://www.cnblogs.com/Sakits/p/8075614.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!