[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 longusing 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()inline LL del(int &now, int l, int r, int x, int f, int h)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)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()++size[0];insert(root[0], 1, M, size[0], a);}return 0;}

  

就让这个题作为我回归奥赛的开端,SDOI2018加油!



上一篇:[luoguP1131] [ZJOI2007]时态同步(贪心)

下一篇:[luoguP1129] [ZJOI2007]矩阵游戏(二分图最大匹配)


线段树 树状数组 splay
Copyright © 2002-2019 k262电脑网 www.k262.cn 皖ICP备2020016292号
温馨提示:部分文章图片数据来源与网络,仅供参考!版权归原作者所有,如有侵权请联系删除!QQ:251442993 热门搜索 网站地图