【NOIP题解】NOIP2017 TG D2T3 列队
列队,NOIP2017 TG D2T3。
树状数组经典题。
题目链接:洛谷。
题意:
Sylvia 是一个热爱学习的女孩子。
前段时间,Sylvia 参加了学校的军训。众所周知,军训的时候需要站方阵。
Sylvia 所在的方阵中有\(n \times m\)名学生,方阵的行数为 \(n\),列数为 \(m\)。
为了便于管理,教官在训练开始时,按照从前到后,从左到右的顺序给方阵中 的学生从 \(1\) 到 \(n \times m\) 编上了号码(参见后面的样例)。即:初始时,第 \(i\) 行第 \(j\) 列 的学生的编号是\((i-1)\times m + j\)。
然而在练习方阵的时候,经常会有学生因为各种各样的事情需要离队。在一天 中,一共发生了 \(q\) 件这样的离队事件。每一次离队事件可以用数对\((x,y) (1 \leq x \leq n, 1 \leq y \leq m)\)描述,表示第 \(x\) 行第 \(y\) 列的学生离队。
在有学生离队后,队伍中出现了一个空位。为了队伍的整齐,教官会依次下达 这样的两条指令:
向左看齐。这时第一列保持不动,所有学生向左填补空缺。不难发现在这条 指令之后,空位在第 \(x\) 行第 \(m\) 列。
向前看齐。这时第一行保持不动,所有学生向前填补空缺。不难发现在这条 指令之后,空位在第 \(n\) 行第 \(m\) 列。
教官规定不能有两个或更多学生同时离队。即在前一个离队的学生归队之后, 下一个学生才能离队。因此在每一个离队的学生要归队时,队伍中有且仅有第 \(n\) 行 第 \(m\) 列一个空位,这时这个学生会自然地填补到这个位置。
因为站方阵真的很无聊,所以 Sylvia 想要计算每一次离队事件中,离队的同学 的编号是多少。
注意:每一个同学的编号不会随着离队事件的发生而改变,在发生离队事件后 方阵中同学的编号可能是乱序的。
题解:
注意到这个方阵被分成了最右侧一列,左侧\(m-1\)列的每一行,共\(n\)行这\(n+1\)个序列。
操作的本质是:每次从其中一个序列中删除一个值,然后在一个序列中加入一个值。
考虑前50%的部分分:
q是非常小的,我们发现可以把与\(x_i\)无关的行排除掉,因为这些行根本不会有操作。
然后维护每行和最后一列即可。
那么前80%呢?
前50%见上文。下面是后30%
注意到所有的操作只在第一行。
我们考虑把第一行和最后一列并在一起,形成新的序列。
这个序列要支持:删除第\(k\)个元素,在末尾加入元素。
可以使用平衡树实现,但是NOIP不考啊?
考虑用树状数组做?怎么做?树状数组维护这一位有没有元素,\(0\)就是没有,\(1\)就是有。
第\(k\)位就是前缀和等于\(k\)。
删除就是\(1\to 0\)。
添加就是\(0\to 1\),特别的,在末尾添加只要记一个末尾的指针就好了。
怎么找第k位?
树状数组上二分,\(O(log n)\)。
那么100%的数据呢?
发现这个矩阵开始的每一位都确定。
如果我们不维护每一行原来的元素,而是维护新加进来的元素呢?
新加进来的元素总数不会超过\(q\)。
而原来的元素可以直接得到。对于每一行,开一个树状数组来维护答案即可。
这个做法要求离线做,先对所有询问按照\(x_i\)排序,然后按照60%~80%的方法维护。
最后把每行的树状数组(合起来不超过\(q\)个元素),和最后一列的放在一起维护就好了。
时间复杂度\(O(qlog(q)+qlog(m+n+q))\)。
我的代码使用了指针来指向多棵树状数组,是洛谷跑的最快的!1488ms!
代码如下:
#pragma GCC optimize("O2")
#include<cstdio>
#include<cstring>
#include<algorithm>
#define F(i,a,b) for(int i=a;i<=b;++i)
#define dF(i,a,b) for(int i=a;i>=b;--i)
#define F2(i,a,b) for(int i=a;i<b;++i)
#define getchar() (SS==TT&&(TT=(SS=BB)+fread(BB,1,1<<15,stdin),TT==SS)?EOF:*SS++)
#define RR register
char BB[<<],*SS=BB,*TT=BB;
inline int read(){
RR int x;RR bool f;RR char c;
for (f=; (c=getchar())<''||c>''; f=c=='-');
for (x=c-''; (c=getchar())>=''&&c<=''; x=(x<<)+(x<<)+c-'');
return f?-x:x;
}
using namespace std;
int q,I[];
long long n,m,a[],b[];
inline bool cmp(int p1,int p2){return a[p1]==a[p2]?p1<p2:a[p1]<a[p2];}
int h[],len[],len2[],bit[];
long long arr[];
long long Ans[];
inline void Ins(int*array,int siz,int i,int x){for(;i<=siz;array[i]+=x,i+=i&-i);}
inline int binary(int*array,int siz,int x){
int l=,r,mid,sum,ans;
while(l<=siz&&array[l]<x) l<<=, ans=l;
r=l; sum=array[l>>=];
while(l<r-){
mid=l+r>>;
if(mid>siz||array[mid]+sum>=x) r=mid, ans=mid;
else l=mid, sum+=array[l];
} ans=r;
return ans;
}
int stk[],top;
int main(){
n=read(), m=read(), q=read();
F(i,,q) a[i]=read(), b[i]=read(), I[i]=i;
sort(I+,I+q+,cmp);
F(i,,m-) Ins(bit,m-,i,);
F(i,,n) len[i]=m-;
F(i,,q){
if(a[I[i-]]!=a[I[i]])
while(top) Ins(bit,m-,stk[top--],);
if(b[I[i]]>len[a[I[i]]]) continue;
int pos=binary(bit,m-,b[I[i]]);
Ans[I[i]]=(a[I[i]]-)*m+pos;
Ins(bit,m-,pos,-);
stk[++top]=pos;
--len[a[I[i]]];
}
int iter=;
F(i,,n){
while(iter<=q&&a[I[iter]]<i) ++iter;
h[i]=iter-;
}
h[n+]=q;
memset(bit,,sizeof bit);
F(i,,n) len[i]=, len2[i]=m-; len[n+]=n;
F(i,,n) Ins(bit+h[n+],n+q,i,), arr[q+i]=i*m;
F(i,,q){
if(Ans[i]){
int pos=binary(bit+h[n+],n+q,a[i]);
Ins(bit+h[n+],n+q,pos,-);
Ins(bit+h[n+],n+q,++len[n+],);
arr[h[n+]+len[n+]]=Ans[i];
Ins(bit+h[a[i]],h[a[i]+]-h[a[i]],++len[a[i]],);
arr[h[a[i]]+len[a[i]]]=arr[h[n+]+pos];
--len2[a[i]];
}
else{
int pos=binary(bit+h[n+],n+q,a[i]);
Ins(bit+h[n+],n+q,pos,-);
Ins(bit+h[n+],n+q,++len[n+],);
if(b[i]!=m){
int pos2=binary(bit+h[a[i]],h[a[i]+]-h[a[i]],b[i]-len2[a[i]]);
Ins(bit+h[a[i]],h[a[i]+]-h[a[i]],pos2,-);
Ans[i]=arr[h[a[i]]+pos2];
Ins(bit+h[a[i]],h[a[i]+]-h[a[i]],++len[a[i]],);
arr[h[a[i]]+len[a[i]]]=arr[h[n+]+pos];
} else Ans[i]=arr[h[n+]+pos];
arr[h[n+]+len[n+]]=Ans[i];
}
}
F(i,,q) printf("%lld\n",Ans[i]);
return ;
}
【NOIP题解】NOIP2017 TG D2T3 列队的更多相关文章
- [NOIP2017 TG D2T3]列队
题目大意:有一个$n \times m$的方阵,第$i$行第$j$列的人的编号是$(i-1) \times m + j$. 现在有$q$个出列操作,每次让一个人出列,然后让这个人所在行向左看齐,再让最 ...
- [NOIp2017提高组]列队
[NOIp2017提高组]列队 题目大意 一个\(n\times m(n,m\le3\times10^5)\)的方阵,每个格子里的人都有一个编号.初始时第\(i\)行第\(j\)列的编号为\((i-1 ...
- 【学术篇】NOIP2017 d2t3 列队phalanx splay做法
我可去他的吧.... ==============先胡扯些什么的分割线================== 一道NOIP题我调了一晚上...(其实是因为昨晚没有找到调试的好方法来的说...) 曾经我以 ...
- NOIP2017 D2T3列队
这题我改了三天,考场上部分分暴力拿了50,考完试发现与正解很接近只是没写出来. 对于每一行和最后一列建n+1颗线段树,维护前缀和. 复杂度qlogn 假如你移动一个坐标为(x,y)的人,你要将第x行线 ...
- NOIP 2014 pj & tg
由于我太弱,去了pj组= = ============================== T1: 傻逼暴力 T2: 傻逼暴力+判断+更新 T3: 手画一下就知道了.算出这个点在第几圈,再使劲yy下在 ...
- 【NOIP 2017】Day2 T3 列队
Problem Description \(Sylvia\) 是一个热爱学习的女孩子. 前段时间,\(Sylvia\) 参加了学校的军训.众所周知,军训的时候需要站方阵. \(Sylvia\) 所在的 ...
- noip2017 TG 游记
嗨小朋友们大家好,还记得我是谁吗?我就是为GG代言的蒟蒻--xzz 今天呐我特别的要向HN的dalao们ZJ的巨佬们还有全国的神犇们问声好 为什么呢因为我们在2017年11月份来到了吔屎的长沙理工大学 ...
- [NOIP2015 TG D2T3]运输计划
题目大意: 给你一棵n个节点的树,有边权,有多个任务,每个要求从ui号节点到 vi号节点去.m 个计划, 这 m 个计划会同时开始.当这 m 个任务都完成时,工作完成. 现在可以把任意一个边的边权变为 ...
- [NOIP2016 TG D2T3]愤怒的小鸟
题目大意:有一架弹弓位于(0,0)处,每次可以用它向第一象限发射一只小鸟,飞行轨迹均为形如y=ax2+bxy=ax+bx2 y=ax2+bx的曲线,且必须满足a<0(即是下开口的) 平面的第一象 ...
随机推荐
- BZOJ 3173 最长上升子序列(树状数组+二分+线段树)
给定一个序列,初始为空.现在我们将1到N的数字插入到序列中,每次将一个数字插入到一个特定的位置.每插入一个数字,我们都想知道此时最长上升子序列长度是多少? 由于序列是顺序插入的,所以当前插入的数字对之 ...
- Linux下的bash对拍
下面是Linux下的bash对拍程序: #!/bin/bash t=0 //数据组数 while true; do let "t=$t + 1" echox printf $t / ...
- Luogu 3369 我用线段树骗了一道平衡树题……
这篇博客毫无意义-- 只是表达一下我仍然会写树状数组和线段树-- 题目链接 #include <cstdio> #include <cstring> #include < ...
- tokenizer
http://blog.csdn.net/beyond__devil/article/details/52829241
- Google Gson用法
the latest version is 2.8.0. If you're using Gradle, add the following line: compile 'com.google.cod ...
- 2018.10.20 2018-2019 ICPC,NEERC,Southern Subregional Contest(Online Mirror, ACM-ICPC Rules)
i207M的“怕不是一个小时就要弃疗的flag”并没有生效,这次居然写到了最后,好评=.= 然而可能是退役前和i207M的最后一场比赛了TAT 不过打得真的好爽啊QAQ 最终结果: 看见那几个罚时没, ...
- 【Asp.net入门08】第一个Asp.net应用程序-创建窗体并设置其样式
本节内容: 添加一个aspx窗体并设计窗体内容 为aspx窗体添加样式 前面我们为PartyInvites应用程序项目添加了两个c#文件:GuestResponse.cs和ResponseReposi ...
- Python 装饰器(进阶篇)
装饰器是什么呢? 我们先来打一个比方,我写了一个python的插件,提供给用户使用,但是在使用的过程中我添加了一些功能,可是又不希望用户改变调用的方式,那么该怎么办呢? 这个时候就用到了装饰器.装饰器 ...
- 「Vue」v-on修饰符
修饰符stop阻止冒泡 --> <!-- <div id="myvue" @click="divc" class="d1" ...
- Java上传文件夹(Jersey)
背景介绍:公司要在CMS系统上为运营人员提供一个功能供运营人员将做好的活动页面上传到阿里云存储上,上传的内容为一个文件夹,文件夹内部有.html网页,JS文件夹下有JS文件,CSS文件夹下有样式表,I ...