题目大意:有一个$n \times m$的方阵,第$i$行第$j$列的人的编号是$(i-1) \times m + j$。

现在有$q$个出列操作,每次让一个人出列,然后让这个人所在行向左看齐,再让最后一列向前看齐,最后让这个人站到第$n$行第$m$列的位置。

你需要输出每次出列的人的编号。

题解:可以每行维护一棵平衡树,再给最后一列维护一棵平衡树(虽然正解是用树状数组)。

发现每行的人初始编号是连续的,而对于$9 \times 10 ^ {10}$的人数,$3 \times 10 ^ {5}$次询问改变的人数其实并不多。

所以,我们把同一行内编号连续的一段缩成一个点,然后需要出列时再分裂即可。

卡点:因为正解是树状数组,所以我洛谷被玄学卡$RE$($UOJ$过的),数组大小调了好几次,然后发现开$O(2)$,数组开的比$UOJ$大一些就不$RE$了。。。

C++ Code:(洛谷)

// luogu-judger-enable-o2
#include <cstdio>
#include <cstdlib>
#define maxn 5500010
using namespace std;
struct node{
int l, r;
long long head;
void operator -= (long long a) {l -= a; r -= a;}
} val[maxn];
int n, m, q;
int lc[maxn], rc[maxn], num[maxn], sz[maxn], tg[maxn], idx;
struct treap {
int root, len;
int ta, tb, tmp, tmp6;
int nw(node x) {
val[++idx] = x;
sz[idx] = 1;
num[idx] = rand();
lc[idx] = rc[idx] = 0;
return idx;
}
void update(int p) {sz[p] = sz[lc[p]] + sz[rc[p]] + 1;}
void pushdown(int p) {
tmp6 = tg[p]; tg[p] = 0;
val[lc[p]] -= tmp6;
val[rc[p]] -= tmp6;
tg[lc[p]] += tmp6;
tg[rc[p]] += tmp6;
}
void splitl(int rt, int k, int &x, int &y) {
if (!rt) x = y = 0;
else {
if (val[rt].l <= k) splitl(rc[rt], k, rc[rt], y), x = rt;
else splitl(lc[rt], k, x, lc[rt]), y = rt;
update(rt);
}
}
void splitr(int rt, int k, int &x, int &y) {
if (!rt) x = y = 0;
else {
pushdown(rt);
if (val[rt].r <= k) splitr(rc[rt], k, rc[rt], y), x = rt;
else splitr(lc[rt], k, x, lc[rt]), y = rt;
update(rt);
}
}
int merge(int x, int y) {
if (!x || !y) return x | y;
if (num[x] > num[y]) {
pushdown(x);
rc[x] = merge(rc[x], y);
update(x);
return x;
} else {
pushdown(y);
lc[y] = merge(x, lc[y]);
update(y);
return (y);
}
}
void build(node p) {
root = nw(p);
}
void insert(long long p, int k = -1){
if (k == -1) k = len;
if (!root) root = nw((node) {k, k, p});
else root = merge(root, nw((node) {k, k, p}));
}
long long nxt(int k) {
splitr(root, k - 1, ta, tmp);
splitl(tmp, k, tmp, tb);
int a = nw((node) {val[tmp].l, k - 1, val[tmp].head}),
b = nw((node) {k + 1, val[tmp].r, val[tmp].head + k + 1 - val[tmp].l});
tb = merge(b, tb);
tg[tb]++;
val[tb] -= 1;
root = merge(merge(ta, a), tb);
return k - val[tmp].l + val[tmp].head;
}
} s[300010], back;
int main() {
srand(20040826);
scanf("%d%d%d", &n, &m, &q);
back.len = n;
for (long long i = 1; i <= n; i++) back.insert(i * m, i);
for (long long i = 1; i <= n; i++) {
s[i].len = m - 1;
s[i].build((node){1, m - 1, (i - 1) * m + 1});
}
int x, y;
long long ta, tb;
while (q--) {
scanf("%d%d", &x, &y);
if (y != m) {
ta = s[x].nxt(y);
tb = back.nxt(x);
s[x].insert(tb);
back.insert(ta);
} else {
ta = back.nxt(x);
back.insert(ta);
}
printf("%lld\n", ta);
}
return 0;
}

  

C++ Code:(UOJ)

#include <cstdio>
#include <cstdlib>
#define maxn 5000010
using namespace std;
struct node{
int l, r;
long long head;
void operator -= (long long a) {l -= a; r -= a;}
} val[maxn];
int n, m, q;
int lc[maxn], rc[maxn], num[maxn], sz[maxn], tg[maxn], idx;
struct treap {
int root, len;
int ta, tb, tmp;
int nw(node x) {
val[++idx] = x;
sz[idx] = 1;
num[idx] = rand();
lc[idx] = rc[idx] = 0;
return idx;
}
void update(int p) {sz[p] = sz[lc[p]] + sz[rc[p]] + 1;}
void pushdown(int p) {
int tmp6 = tg[p]; tg[p] = 0;
val[lc[p]] -= tmp6;
val[rc[p]] -= tmp6;
tg[lc[p]] += tmp6;
tg[rc[p]] += tmp6;
}
void splitl(int rt, int k, int &x, int &y) {
if (!rt) x = y = 0;
else {
if (val[rt].l <= k) splitl(rc[rt], k, rc[rt], y), x = rt;
else splitl(lc[rt], k, x, lc[rt]), y = rt;
update(rt);
}
}
void splitr(int rt, int k, int &x, int &y) {
if (!rt) x = y = 0;
else {
pushdown(rt);
if (val[rt].r <= k) splitr(rc[rt], k, rc[rt], y), x = rt;
else splitr(lc[rt], k, x, lc[rt]), y = rt;
update(rt);
}
}
int merge(int x, int y) {
if (!x || !y) return x | y;
if (num[x] > num[y]) {
pushdown(x);
rc[x] = merge(rc[x], y);
update(x);
return x;
} else {
pushdown(y);
lc[y] = merge(x, lc[y]);
update(y);
return (y);
}
}
void build(node p) {
root = nw(p);
}
void insert(long long p, int k = -1){
if (k == -1) k = len;
if (!root) root = nw((node) {k, k, p});
else root = merge(root, nw((node) {k, k, p}));
}
long long nxt(int k) {
splitr(root, k - 1, ta, tmp);
splitl(tmp, k, tmp, tb);
int a = nw((node) {val[tmp].l, k - 1, val[tmp].head}),
b = nw((node) {k + 1, val[tmp].r, val[tmp].head + k + 1 - val[tmp].l});
tb = merge(b, tb);
tg[tb]++;
val[tb] -= 1;
root = merge(merge(ta, a), tb);
return k - val[tmp].l + val[tmp].head;
}
} s[300010], back;
int main() {
srand(20040826);
scanf("%d%d%d", &n, &m, &q);
back.len = n;
for (long long i = 1; i <= n; i++) back.insert(i * m, i);
for (long long i = 1; i <= n; i++) {
s[i].len = m - 1;
s[i].build((node){1, m - 1, (i - 1) * m + 1});
}
int x, y;
long long ta, tb;
while (q--) {
scanf("%d%d", &x, &y);
if (y != m) {
ta = s[x].nxt(y);
tb = back.nxt(x);
s[x].insert(tb);
back.insert(ta);
} else {
ta = back.nxt(x);
back.insert(ta);
}
printf("%lld\n", ta);
}
return 0;
}

  

[NOIP2017 TG D2T3]列队的更多相关文章

  1. 【NOIP题解】NOIP2017 TG D2T3 列队

    列队,NOIP2017 TG D2T3. 树状数组经典题. 题目链接:洛谷. 题意: Sylvia 是一个热爱学习的女孩子. 前段时间,Sylvia 参加了学校的军训.众所周知,军训的时候需要站方阵. ...

  2. [NOIp2017提高组]列队

    [NOIp2017提高组]列队 题目大意 一个\(n\times m(n,m\le3\times10^5)\)的方阵,每个格子里的人都有一个编号.初始时第\(i\)行第\(j\)列的编号为\((i-1 ...

  3. 【学术篇】NOIP2017 d2t3 列队phalanx splay做法

    我可去他的吧.... ==============先胡扯些什么的分割线================== 一道NOIP题我调了一晚上...(其实是因为昨晚没有找到调试的好方法来的说...) 曾经我以 ...

  4. NOIP2017 D2T3列队

    这题我改了三天,考场上部分分暴力拿了50,考完试发现与正解很接近只是没写出来. 对于每一行和最后一列建n+1颗线段树,维护前缀和. 复杂度qlogn 假如你移动一个坐标为(x,y)的人,你要将第x行线 ...

  5. noip2017 TG 游记

    嗨小朋友们大家好,还记得我是谁吗?我就是为GG代言的蒟蒻--xzz 今天呐我特别的要向HN的dalao们ZJ的巨佬们还有全国的神犇们问声好 为什么呢因为我们在2017年11月份来到了吔屎的长沙理工大学 ...

  6. NOIP2017 Day2 T3 列队(treap)

    可以直接用treap上大模拟...n+1个treap维护n行的前m-1个点和最后一列. 需要支持删除一个点或者一段区间,而空间并不支持存下所有的点的时候,可以用一个点代替一个区间,记录区间首项的值和区 ...

  7. [NOIP2015 TG D2T3]运输计划

    题目大意: 给你一棵n个节点的树,有边权,有多个任务,每个要求从ui号节点到 vi号节点去.m 个计划, 这 m 个计划会同时开始.当这 m 个任务都完成时,工作完成. 现在可以把任意一个边的边权变为 ...

  8. [NOIP2016 TG D2T3]愤怒的小鸟

    题目大意:有一架弹弓位于(0,0)处,每次可以用它向第一象限发射一只小鸟,飞行轨迹均为形如y=ax2+bxy=ax+bx2 y=ax2+bx的曲线,且必须满足a<0(即是下开口的) 平面的第一象 ...

  9. [NOIP2017 TG D2T2]宝藏(模拟退火)

    题目大意:$NOIPD2T2$宝藏 题解:正常做法:状压DP .这次模拟退火,随机一个排列,$O(n^2)$贪心按排列的顺序加入生成树 卡点:没开$long\;long$,接受较劣解时判断打错,没判$ ...

随机推荐

  1. Apache Maven(五):插件

    Maven的插件分如下两种: build plugins:该插件在项目构建阶段执行,它们都在<build>标签中设置. reporting plugins : 该插件在网站生成期间执行,他 ...

  2. ECSHOP快递单号查询插件圆通V8.2专版

    本ECSHOP快递物流单号跟踪插件提供国内外近2000家快递物流订单单号查询服务例如申通快递.顺丰快递.圆通快递.EMS快递.汇通快递.宅急送快递.德邦物流.百世快递.汇通快递.中通快递.天天快递等知 ...

  3. [MIP]mip-script组件自定义 JS 代码使用限制

    自mip升级v2版本后,多了一个mip-script组件,很多人就都以为可以写自定义js代码了!然并卵,MIP2页中还是一样不允许自定义javascript代码,所有的交互须通过组件实现. 引用官方说 ...

  4. ARM串口控制终端命令

    配置开发板eth0网络: # ifconfig eth0 10.70.12.168

  5. 数据分析处理库Pandas——常用操作

    DataFrame结构排序 备注:group列降序,data列升序. 合并相同项 查找相同项 添加一列,值是其他列的值进行相关操作后的值 删除列 Series结构替换值 一组值按照范围归类 归类后每类 ...

  6. Linux 控制台

    shell shell命令分为两种:分别是内部命令和外部命令. 内部命令:在安装的时候嵌入系统内核. 外部命令:以文件的形式存在. 可以使用type命令查看是内部命令还是外部命令. Linux中,默认 ...

  7. spring+springmvc+maven+mongodb

    1.前言 最近项目开发使用到了spring+springmvc+maven+mongodb,项目中的框架是用springboot进项开发的,对于我们中级开发人员来说,有利有弊,好处呢是springbo ...

  8. ORB-SLAM (四)tracking跟踪解析

    初始化完成后,对于相机获取当前图像mCurrentFrame,通过跟踪匹配上一帧mLastFrame特征点的方式,可以获取一个相机位姿的初始值:为了兼顾计算量和跟踪鲁棒性,处理了三种模型: 1. Tr ...

  9. 【jQuery】 资料

    [jQuery] 资料 1. 选择器 http://www.w3school.com.cn/jquery/jquery_ref_selectors.asp 2. 事件 http://www.w3sch ...

  10. web端常见兼容性问题整理

    一.html和css 各浏览器的默认内外边距不一致问题 最明显的是ul标签内外边距问题,ul标签在IE-7中,有个默认的外边距,但是在IE8以上及其他浏览器中有个默认的内边距. 解决办法:*{marg ...