[luoguP3960] 列队(动态开点线段树)
有splay的做法,有树状数组的做法。。。
最好理解的还是线段树的做法。
一开始我是这样想的,如果移动某一个人,只有当前行和最后一列会受到影响,感觉就像是个线段树,树状数组什么的。
然而接下来就想歪了,把一个人移到后面,等于把后面的整体往前移一格,gg
正确思路是权值线段树,如果一个数被移走,相当于这个数的个数-1,然后把它变成了m+1,放到后面。
移动第x行第y个人其实就是求第x行的第y大。
这样,每一行和最后一列建一棵线段树,然而超空间。
所以需要动态开点,因为总共只移动3*10^5次,也就是开nlongn的点。
据说逆向思维可以骗50分,这都没想到。。。
最后附上丑陋的,调了一晚上的,连我自己都看不懂的代码——
#include <cstdio>
#include <cstring>
#include <iostream>
#define N 600001
#define LL long long using namespace std; int n, m, q, M, cnt;
int size[N], sum[N * 10], ls[N * 10], rs[N * 10], root[N];
LL val[N * 10]; inline int read()
{
int x = 0, f = 1;
char ch = getchar();
for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0';
return x * f;
} inline LL del(int &now, int l, int r, int x, int f, int h)
{
if(!now) now = ++cnt;
sum[now]--;
if(l == r)
{
if(!f) return val[now] ? val[now] : (LL)(h - 1) * m + l;
return val[now] ? val[now] : (LL)l * m;
}
int mid = (l + r) >> 1;
if(mid - l + 1 + sum[ls[now]] >= x) return del(ls[now], l, mid, x, f, h);
else return del(rs[now], mid + 1, r, x - (mid - l + 1 + sum[ls[now]]), f, h);
} inline void insert(int &now, int l, int r, int x, LL d)
{
if(!now) now = ++cnt;
if(l == r)
{
val[now] = d;
return;
}
int mid = (l + r) >> 1;
if(x <= mid) insert(ls[now], l, mid, x, d);
else insert(rs[now], mid + 1, r, x, d);
} int main()
{
int i, x, y;
LL a, b;
n = read();
m = read();
q = read();
M = max(n, m) + q;
size[0] = n;
for(i = 1; i <= n; i++) size[i] = m - 1;
while(q--)
{
x = read();
y = read();
if(y != m) a = del(root[x], 1, M, y, 0, x);
b = del(root[0], 1, M, x, 1, x);
printf("%lld\n", y == m ? a = b : a);
if(y != m)
{
++size[x];
insert(root[x], 1, M, size[x], b);
}
++size[0];
insert(root[0], 1, M, size[0], a);
}
return 0;
}
就让这个题作为我回归奥赛的开端,SDOI2018加油!
[luoguP3960] 列队(动态开点线段树)的更多相关文章
- Luogu P3960 列队(动态开点线段树)
P3960 列队 题意 题目描述 Sylvia 是一个热爱学习的女孩子. 前段时间,Sylvia 参加了学校的军训.众所周知,军训的时候需要站方阵. Sylvia所在的方阵中有\(n \times m ...
- NOIP2017 列队——动态开点线段树
Description: Sylvia 是一个热爱学习的女♂孩子. 前段时间,Sylvia 参加了学校的军训.众所周知,军训的时候需要站方阵. Sylvia 所在的方阵中有n×m名学生,方阵的行数为 ...
- 洛谷P3960 列队(动态开节点线段树)
题意 题目链接 Sol 看不懂splay..,看不懂树状数组... 只会暴力动态开节点线段树 观察之后不难发现,我们对于行和列需要支持的操作都是相同的:找到第\(k\)大的元素并删除,在末尾插入一个元 ...
- [2016湖南长沙培训Day4][前鬼后鬼的守护 chen] (动态开点线段树+中位数 or 动规 or 贪心+堆优化)
题目大意 给定一个长度为n的正整数序列,令修改一个数的代价为修改前后两个数的绝对值之差,求用最小代价将序列转换为不减序列. 其中,n满足小于500000,序列中的正整数小于10^9 题解(引自mzx神 ...
- [bzoj 3531][SDOI2014]旅行(树链剖分+动态开点线段树)
题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=3531 分析: 对于每个颜色(颜色<=10^5)都建立一颗线段树 什么!那么不是M ...
- 【BZOJ-4636】蒟蒻的数列 动态开点线段树 ||(离散化) + 标记永久化
4636: 蒟蒻的数列 Time Limit: 30 Sec Memory Limit: 256 MBSubmit: 247 Solved: 113[Submit][Status][Discuss ...
- codeforces 893F - Physical Education Lessons 动态开点线段树合并
https://codeforces.com/contest/893/problem/F 题意: 给一个有根树, 多次查询,每次查询对于$x$i点的子树中,距离$x$小于等于$k$的所有点中权值最小的 ...
- codeforces 915E - Physical Education Lessons 动态开点线段树
题意: 最大$10^9$的区间, $3*10^5$次区间修改,每次操作后求整个区间的和 题解: 裸的动态开点线段树,计算清楚数据范围是关键... 经过尝试 $2*10^7$会$MLE$ $10^7$会 ...
- CF915E Physical Education Lessons 动态开点线段树
题目链接 CF915E Physical Education Lessons 题解 动态开点线段树 代码 /* 动态开点线段树 */ #include<cstdio> #include&l ...
- 洛谷P3313 [SDOI2014]旅行(树链剖分 动态开节点线段树)
题意 题目链接 Sol 树链剖分板子 + 动态开节点线段树板子 #include<bits/stdc++.h> #define Pair pair<int, int> #def ...
随机推荐
- nl
-b -b -a 表示不论是否为空行,也同样列出行号 -b -t 如果用空行,空行不要列出行号 -n 列出行号表示方法,主要有3中 -n -n ln 行号显示在屏幕的最左方显示 -n rn 行号显示在 ...
- PHP-PHPExcel用法详解
以下文章来源:diandian_520 http://blog.csdn.net/diandian_520/article/details/7827038 1.header header(" ...
- Linux基础知识介绍
1.Linux知识说明1)文件位置 1)/etc/inittab2)模式介绍 0:挂起模式-不推荐 1:单用户模式-只有管理员可以进入该模式,可以修改root密码,处理有登录权限而没有修改文件的权限问 ...
- 00_HTTP协议介绍
1. 什么是HTTP协议 协议是指计算机通信网络中两台计算机之间进行通信所必须共同遵守的规定或规则,超文本传输协议(HTTP)是一种通信协议,它允许将超文本标记语言(HTML)文档从Web服务器传送到 ...
- haproxy文件的增删改查
在构建一个程序项目之前,首先需要设计程序的框架,从总体上构建一个项目中的一个个功能,之后对每一个功能进行补充,最终实现总体的功能. 1 程序的总体框架: 首先把所有的功能设计成相应的函数,用pass来 ...
- Robotium实践之路源码创建测试项目
1.JDK安装及环境配置 2.Eclipse安装 3.ADT插件安装 4.模拟器安装 5.准备源码 6.引进源码置项目中 .文件 .导入 .选择现有项目置工作空间中 .浏览 .选择项目,选择模拟器版本 ...
- JS中鼠标左右键以及中键的事件
在三维场景中有时候需要判断鼠标的事件,除了使用的click事件,只有鼠标左键有效,而右键无效.而对于onmousedown.onmouseup的时候鼠标的事件左键/右键有效.详细请看w3c上的资料. ...
- shell脚本,tee小工具的用法。
解释: tee是个工具 , 它的作用就是把标准输出,复制一份,扔文件里 ,原标准输出还输出,-a就相当于 >> 追加到文件里的意思. 不加就是 > 重定向到文件里去.
- js事件(事件冒泡与事件捕获)
事件冒泡和事件捕获分别由微软和网景公司提出,这两个概念都是为了解决页面中事件流(事件发生顺序)的问题. <div id='aa' click='po'> <p id='bb' cli ...
- Codeforces Round #510 #C Array Product
http://codeforces.com/contest/1042/problem/C 给你一个有n个元素序列,有两个操作:1,选取a[i]和a[j],删除a[i],将$a[i]*a[j]$赋值给a ...