5478. 【NOIP2017提高组正式赛】列队
来源:互联网 发布:淘宝明星店铺 编辑:程序博客网 时间:2024/06/06 18:49
题目描述
Sylvia 是一个热爱学习的女孩子。
前段时间,Sylvia 参加了学校的军训。众所周知,军训的时候需要站方阵。 Sylvia所在的方阵中有n × m名学生,方阵的行数为 n,列数为 m。
为了便于管理,教官在训练开始时,按照从前到后,从左到右的顺序给方阵中从 1 到 n × m 编上了号码(参见后面的样例)。即:初始时,第 i 行第 j 列的学生的编号是(i − 1) × m + j。
然而在练习方阵的时候,经常会有学生因为各种各样的事情需要离队。在一天中,一共发生了 q 件这样的离队事件。每一次离队事件可以用数对(y,z) (1≤x≤n,1≤y≤m)描述,表示第 x 行第 y 列的学生离队。
在有学生离队后,队伍中出现了一个空位。为了队伍的整齐,教官会依次下达这样的两条指令:
1. 向左看齐。这时第一列保持不动,所有学生向左填补空缺。不难发现在这条指令之后,空位在第 x 行第 m 列。
2. 向前看齐。这时第一行保持不动,所有学生向前填补空缺。不难发现在这条指令之后,空位在第 n 行第 m 列。
教官规定不能有两个或更多学生同时离队。即在前一个离队的学生归队之后,下一个学生才能离队。因此在每一个离队的学生要归队时,队伍中有且仅有第 n 行第 m 列一个空位,这时这个学生会自然地填补到这个位置。
因为站方阵真的很无聊,所以 Sylvia 想要计算每一次离队事件中,离队的同学的编号是多少。
注意:每一个同学的编号不会随着离队事件的发生而改变,在发生离队事件后方阵中同学的编号可能是乱序的。
题目分析
这一道题很难。
不过我们发现,整个过程可以总结为2种操作:
1.从序列中找出第k个数并删除。
2.把删除的数加入到序列后面。
这样我们可以用n+1棵线段树来解决。
前n棵是维护每一行的第1列到第m-1列的
第n+1棵是维护第m列的。
关键在于:300000*300000咋整?
只能用动态开点来解决。
如何动态开点?自己看一下代码顺便学习吧。
代码
#include<cstdio>#include<cstring>#include<cstdlib>using namespace std;typedef long long ll;struct node{ int x,y;}a[310000];struct tree{ int lc,rc;ll c;}tr[6100000];int tail[310000],root[310000];int tot=0;int size[6100000];void insert(int &now,int l,int r,int k,ll num){ if(now==0) now=++tot; if(l==r) { tr[now].c=num; size[now]=0; return ; } int mid=(l+r)/2; if(k<=mid) insert(tr[now].lc,l,mid,k,num); else insert(tr[now].rc,mid+1,r,k,num); size[now]=size[tr[now].lc]+size[tr[now].rc];}ll findkth(int &now,int l,int r,int k,int &ans){ if(now==0) now=++tot; if(l==r) { ans=l; ll temp=tr[now].c;tr[now].c=0; size[now]=1; return temp; } int mid=(l+r)/2;ll temp; if(mid-l+1-size[tr[now].lc]>=k) { temp=findkth(tr[now].lc,l,mid,k,ans); } else { temp=findkth(tr[now].rc,mid+1,r,k-(mid-l+1-size[tr[now].lc]),ans); } size[now]=size[tr[now].lc]+size[tr[now].rc]; return temp;}int main(){ ll n,m,q; scanf("%lld%lld%lld",&n,&m,&q); for(int i=1;i<=n;i++) tail[i]=m-1; tail[n+1]=n; for(int i=1;i<=q;i++) { scanf("%d%d",&a[i].x,&a[i].y); if(a[i].y==m) { int temp2; ll temp=findkth(root[n+1],1,n+q,a[i].x,temp2); if(temp2<=n) temp=temp2*m; printf("%lld\n",temp); insert(root[n+1],1,n+q,++tail[n+1],temp); } else { int temp2; ll temp=findkth(root[a[i].x],1,m+q,a[i].y,temp2); if(temp2<m) temp=m*(a[i].x-1)+temp2; printf("%lld\n",temp); insert(root[n+1],1,n+q,++tail[n+1],temp); temp=findkth(root[n+1],1,n+q,a[i].x,temp2); if(temp2<=n) temp=temp2*m; insert(root[a[i].x],1,m+q,++tail[a[i].x],temp); } } return 0;}
- 5478. 【NOIP2017提高组正式赛】列队
- 【NOIP2017提高组正式赛】列队
- 【NOIP2017提高组正式赛】D2T3列队
- JZOJ 5478. 【NOIP2017提高组正式赛】列队
- 【NOIP2017DAY2T3 【NOIP2017提高组正式赛】列队 】(动态开点+n棵线段树)
- jzoj5478. 【NOIP2017提高组】列队
- NOIP2017提高组D2T3[列队]
- 【NOIP2017提高组正式赛】逛公园
- 【NOIP2017提高组正式赛】宝藏
- 5476. 【NOIP2017提高组正式赛】奶酪
- 5477. 【NOIP2017提高组正式赛】宝藏
- 【NOIP2017提高组正式赛】Day1T3逛公园
- JZOJ 5476. 【NOIP2017提高组正式赛】奶酪
- JZOJ 5474. 【NOIP2017提高组正式赛】时间复杂度
- JZOJ 5475. 【NOIP2017提高组正式赛】逛公园
- JZOJ 5477. 【NOIP2017提高组正式赛】宝藏
- 5473. 【NOIP2017提高组正式赛】小凯的疑惑
- 5474. 【NOIP2017提高组正式赛】时间复杂度
- OpenCl_CPU加速矩阵运算
- linux下OpenCV 学习(一) onencv 的安装
- jQuery点赞动画效果+1的代码实现
- Ubuntu 命令手册
- C语言itoa()函数和atoi()函数详解(整数转字符C实现)
- 5478. 【NOIP2017提高组正式赛】列队
- 简单易懂的自动编码器
- 用Hibernate保存对象出现c3p0数据库连接池死锁问题的可能原因
- js跨浏览器添加移除事件
- easyui pagination spring boot 分页程序实现
- PHP学习快速入门
- 应用程序启动原理
- 判断一个数是不是丑数。
- 【深度】从朴素贝叶斯到维特比算法:详解隐马尔科夫模型