NOIP2017 Day2 T3 列队(treap)
可以直接用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=;
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=; k=; char c=getchar();
while(c<'' || c>'') c=='-' && (f=-), c=getchar();
while(c<='' && c>='') k=k*+c-'', c=getchar();
k*=f;
}
inline void build(int &x, ll beg, int len)
{
tree[x=++tott].beg=beg; tree[x].size=;
tree[x].len=Len[x]=len;
tree[x].rnd=rand()<<|rand();
}
inline void up(int x)
{
tree[x].size=tree[lt].size+tree[rt].size+;
tree[x].len=tree[lt].len+tree[rt].len+Len[x];
}
void split(int x, int &l, int &r, int k)
{
if(!k) l=, r=x;
else if(tree[x].size==k) l=x, r=;
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-), 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+;
else if(k<=tree[lt].len) rank(lt, k);
else rk+=tree[lt].size+, 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=; rank(Root, pos);
split(Root, Root, y, rk); if(rk-) split(Root, Root, x, rk-); else x=Root;
if(ans-) build(tmp, tree[x].beg, ans-), merge(Root, Root, tmp);
if(Len[x]-ans) build(tmp, tree[x].beg+ans*(Root==root[n+]?m:), 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-;
build(tmp, ANS, ); merge(root[n+], root[n+], tmp);
disc(root[n+], poi, posx); poi=tree[poi].beg+(ans-)*m;
build(tmp, poi, ); merge(root[posx], root[posx], tmp);
return ANS;
}
ll poi;
disc(root[n+], poi, posx); poi=tree[poi].beg+(ans-)*m;
build(tmp, poi, ); merge(root[n+], root[n+], tmp);
return poi;
}
#undef int
int main()
{
srand();
read(n); read(m); read(Q);
for(int i=;i<=n;i++) build(root[i], 1ll*+(i-)*m, m-); build(root[n+], m, n);
for(int i=;i<=Q;i++) read(x), read(y), printf("%lld\n", query(x, y));
}
线段树好写很多,而且非常快。
可以发现如果不是从最后一列加进来的数的话一定是递增的,那么这些数我们可以直接用n棵权值线段树来维护找第k大即可,把删点改为加点,就不会爆空间,然后剩下从最后一列加进来的直接丢进一个vector里面,如果查询的数不在线段树里就直接在vector里查询。最后一列维护的方法同理。
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#include<vector>
#define ll long long
#define lt tree[x].ls
#define rt tree[x].rs
using namespace std;
const int maxn=;
struct poi{int ls, rs, size;}tree[maxn<<];
vector<ll>h[maxn];
int n, m, q, tott, x, y;
ll mx;
int root[maxn];
inline void read(int &k)
{
int f=; k=; char c=getchar();
while(c<'' || c>'') c=='-' && (f=-), c=getchar();
while(c<='' && c>='') k=k*+c-'', c=getchar();
k*=f;
}
void update(int &x, int l, int r, int cx)
{
if(!x) x=++tott; tree[x].size++;
if(l==r) return;
int mid=(l+r)>>;
if(cx<=mid) update(lt, l, mid, cx);
else update(rt, mid+, r, cx);
}
int query(int x, int l, int r, int k)
{
if(l==r) return l;
int mid=(l+r)>>, lsize=mid-l+-tree[lt].size;
if(lsize>=k) return query(lt, l, mid, k);
return query(rt, mid+, r, k-lsize);
}
inline ll delr(int x, ll y)
{
ll pos=query(root[n+], , mx, x); update(root[n+], , mx, pos);
ll ans=pos<=n?1ll*pos*m:h[n+][pos-n-];
h[n+].push_back(y?y:ans);
return ans;
}
inline ll dell(int x, ll y)
{
ll pos=query(root[x], , mx, y); update(root[x], , mx, pos);
ll ans=pos<m?1ll*(x-)*m+pos:h[x][pos-m];
h[x].push_back(delr(x, ans));
return ans;
}
int main()
{
read(n); read(m); read(q); mx=max(n, m)+q;
for(int i=;i<=q;i++)
{
read(x); read(y);
if(y==m) printf("%lld\n", delr(x, ));
else printf("%lld\n", dell(x, y));
}
}
NOIP2017 Day2 T3 列队(treap)的更多相关文章
- 【NOIP 2017】Day2 T3 列队
Problem Description \(Sylvia\) 是一个热爱学习的女孩子. 前段时间,\(Sylvia\) 参加了学校的军训.众所周知,军训的时候需要站方阵. \(Sylvia\) 所在的 ...
- [NOIp2017提高组]列队
[NOIp2017提高组]列队 题目大意 一个\(n\times m(n,m\le3\times10^5)\)的方阵,每个格子里的人都有一个编号.初始时第\(i\)行第\(j\)列的编号为\((i-1 ...
- NOIP2017 Day1 T3 逛公园
NOIP2017 Day1 T3 更好的阅读体验 题目描述 策策同学特别喜欢逛公园.公园可以看成一张\(N\)个点\(M\)条边构成的有向图,且没有 自环和重边.其中1号点是公园的入口,\(N\)号点 ...
- NOIP2017D2T3 列队—Treap
NOIP2017列队 Description Sylvia 是一个热爱学习的女孩子. 前段时间,Sylvia 参加了学校的军训.众所周知,军训的时候需要站方阵. Sylvia所在的方阵中有n × m ...
- 【NOIP题解】NOIP2017 TG D2T3 列队
列队,NOIP2017 TG D2T3. 树状数组经典题. 题目链接:洛谷. 题意: Sylvia 是一个热爱学习的女孩子. 前段时间,Sylvia 参加了学校的军训.众所周知,军训的时候需要站方阵. ...
- [NOIP2017 TG D2T3]列队
题目大意:有一个$n \times m$的方阵,第$i$行第$j$列的人的编号是$(i-1) \times m + j$. 现在有$q$个出列操作,每次让一个人出列,然后让这个人所在行向左看齐,再让最 ...
- 【BZOJ 4518】【SDOI 2016 Round1 Day2 T3】征途
比较明显的斜率优化DP,省选时因为时间太紧张和斜率DP写得不熟等原因只写了60分的暴力DP,其实当时完全可以对拍来检验标算的正确,但是我当时too naive- 很快打完了,调了将近一晚上QAQ,因为 ...
- 【NOIP 2013 DAY2 T3】 华容道(spfa)
题目描述 [问题描述] 小 B 最近迷上了华容道,可是他总是要花很长的时间才能完成一次.于是,他想到用编程来完成华容道:给定一种局面, 华容道是否根本就无法完成,如果能完成, 最少需要多少时间. 小 ...
- 【NOIP 2015 DAY2 T3】 运输计划 (树链剖分-LCA)
题目背景 公元 2044 年,人类进入了宇宙纪元. 题目描述 L 国有 n 个星球,还有 n-1 条双向航道,每条航道建立在两个星球之间,这 n-1 条航道连通了 L 国的所有星球. 小 P 掌管一家 ...
随机推荐
- appium+python自动化☞appium python api大全
整理了一些常用的appium python api,供学习使用...
- TW实习日记:第七天
今天早上,将项目的两个企业微信接口:登录和应用消息发送接口,做了最后的收尾工作,把目前我能解决的问题算是基本都解决了.早上还开了一个会,大意是组长封装了许多组件叫我们使用,在不断的使用中打磨组件的可用 ...
- 导出Office365中的组及成员
Set-ExecutionPolicy unrestricted $cred = Get-Credential $session = New-PSSession -ConfigurationName ...
- day09,10 函数
一.函数 什么是函数 函数: 对代码块和功能的封装和定义 定义一个事情或者功能. 等到需要的时候直接去用就好了. 那么这里定义的东西就是一个函数. 语法: def 函数名(形参): 函数体 函数名(实 ...
- Logistic回归 逻辑回归 练习——以2018建模校赛为数据源
把上次建模校赛一个根据三围将女性分为四类(苹果型.梨形.报纸型.沙漏)的问题用逻辑回归实现了,包括从excel读取数据等一系列操作. Excel的格式如下:假设有r列,则前r-1列为数据,最后一列为类 ...
- nhibernate中执行SQL语句
在有些时候,可能需要直接执行SQL语句.存储过程等,但nhibernate并没有提供一种让我们执行SQL语句的方法,不过可以通过一些间接的方法来实现. 下面给出一个在nhibernate中执行SQL语 ...
- AndroidArchitecture
title: AndroidArchitecture date: 2016-04-08 23:26:20 tags: [architecture] categories: [Mobile,Androi ...
- 你用 Python 做过什么有趣的数据挖掘项目?
有网友在知乎提问:「你用 Python 做过什么有趣的数据挖掘项目?」 我最近刚开始学习 Python, numpy, scipy 等, 想做一些数据方面的项目,但是之前又没有这方面的经验.所以想知道 ...
- 如何开发一个 PyCharm 插件
PyCharm 是很多 Python 开发者优先选择的 IDE,功能强大,跨平台,提供免费社区版,非常良心.如果你想自己给PyCharm添加一些功能怎么办呢?有两个办法: 通过提需求实现,到 JetB ...
- python 读取blob
for num in range(76802): # if num == 0: # c[num] = imagedata[0:4] # d[num] = struct.unpack('i', c[nu ...