列队,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!

代码如下:

 1 #pragma GCC optimize("O2")
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define F(i,a,b) for(int i=a;i<=b;++i)
 6 #define dF(i,a,b) for(int i=a;i>=b;--i)
 7 #define F2(i,a,b) for(int i=a;i<b;++i)
 8 #define getchar() (SS==TT&&(TT=(SS=BB)+fread(BB,1,1<<15,stdin),TT==SS)?EOF:*SS++)
 9 #define RR register
10 char BB[1<<15],*SS=BB,*TT=BB;
11 inline int read(){
12     RR int x;RR bool f;RR char c;
13     for (f=0; (c=getchar())<'0'||c>'9'; f=c=='-');
14     for (x=c-'0'; (c=getchar())>='0'&&c<='9'; x=(x<<3)+(x<<1)+c-'0');
15     return f?-x:x;
16 }
17 using namespace std;
18 int q,I[300010];
19 long long n,m,a[300010],b[300010];
20 inline bool cmp(int p1,int p2){return a[p1]==a[p2]?p1<p2:a[p1]<a[p2];}
21 int h[300010],len[300010],len2[300010],bit[900010];
22 long long arr[900010];
23 long long Ans[300010];
24 inline void Ins(int*array,int siz,int i,int x){for(;i<=siz;array[i]+=x,i+=i&-i);}
25 inline int binary(int*array,int siz,int x){
26     int l=1,r,mid,sum,ans;
27     while(l<=siz&&array[l]<x) l<<=1, ans=l;
28     r=l; sum=array[l>>=1];
29     while(l<r-1){
30         mid=l+r>>1;
31         if(mid>siz||array[mid]+sum>=x) r=mid, ans=mid;
32         else l=mid, sum+=array[l];
33     } ans=r;
34     return ans;
35 }
36 int stk[300001],top;
37 int main(){
38     n=read(), m=read(), q=read();
39     F(i,1,q) a[i]=read(), b[i]=read(), I[i]=i;
40     sort(I+1,I+q+1,cmp);
41     F(i,1,m-1) Ins(bit,m-1,i,1);
42     F(i,1,n) len[i]=m-1;
43     F(i,1,q){
44         if(a[I[i-1]]!=a[I[i]])
45             while(top) Ins(bit,m-1,stk[top--],1);
46         if(b[I[i]]>len[a[I[i]]]) continue;
47         int pos=binary(bit,m-1,b[I[i]]);
48         Ans[I[i]]=(a[I[i]]-1)*m+pos;
49         Ins(bit,m-1,pos,-1);
50         stk[++top]=pos;
51         --len[a[I[i]]];
52     }
53     int iter=0;
54     F(i,1,n){
55         while(iter<=q&&a[I[iter]]<i) ++iter;
56         h[i]=iter-1;
57     }
58     h[n+1]=q;
59     memset(bit,0,sizeof bit);
60     F(i,1,n) len[i]=0, len2[i]=m-1; len[n+1]=n;
61     F(i,1,n) Ins(bit+h[n+1],n+q,i,1), arr[q+i]=i*m;
62     F(i,1,q){
63         if(Ans[i]){
64             int pos=binary(bit+h[n+1],n+q,a[i]);
65             Ins(bit+h[n+1],n+q,pos,-1);
66             Ins(bit+h[n+1],n+q,++len[n+1],1);
67             arr[h[n+1]+len[n+1]]=Ans[i];
68             Ins(bit+h[a[i]],h[a[i]+1]-h[a[i]],++len[a[i]],1);
69             arr[h[a[i]]+len[a[i]]]=arr[h[n+1]+pos];
70             --len2[a[i]];
71         }
72         else{
73             int pos=binary(bit+h[n+1],n+q,a[i]);
74             Ins(bit+h[n+1],n+q,pos,-1);
75             Ins(bit+h[n+1],n+q,++len[n+1],1);
76             if(b[i]!=m){
77                 int pos2=binary(bit+h[a[i]],h[a[i]+1]-h[a[i]],b[i]-len2[a[i]]);
78                 Ins(bit+h[a[i]],h[a[i]+1]-h[a[i]],pos2,-1);
79                 Ans[i]=arr[h[a[i]]+pos2];
80                 Ins(bit+h[a[i]],h[a[i]+1]-h[a[i]],++len[a[i]],1);
81                 arr[h[a[i]]+len[a[i]]]=arr[h[n+1]+pos];
82             } else Ans[i]=arr[h[n+1]+pos];
83             arr[h[n+1]+len[n+1]]=Ans[i];
84         }
85     }
86     F(i,1,q) printf("%lld\n",Ans[i]);
87     return 0;
88 }

View Code

转载于:https://www.cnblogs.com/PinkRabbit/p/8214292.html

【NOIP题解】NOIP2017 TG D2T3 列队相关推荐

  1. 【题解】[NOIP2017 提高组] 列队

    题意 给定一个 n*m 的队列,每次操作选取一个位置 (i,j) 出队,然后填补空位.输出每次出队的编号. Solution: 考点:模拟+数据结构. 算法一 对于 n,m<=1000 的数据, ...

  2. 【NOIP 2017】Day2 T3 列队

    Problem Description \(Sylvia\) 是一个热爱学习的女孩子. 前段时间,\(Sylvia\) 参加了学校的军训.众所周知,军训的时候需要站方阵. \(Sylvia\) 所在的 ...

  3. 2020第二场NOIP|题解

    值得我们庆幸的是NOIP恢复了 当然 我为你们准备了题解 未了[endless]|题解 荆轲刺秦王[bandit]|题解 建设城市[city]|题解 有问题可以在下边提出来记得 @Y_bluefat

  4. [NOIP2017 TG D2T2]宝藏

    题目大意:给定一个有重边,边有权值的无向图.从某一个点出发,求到达所有的点需要的最少费用,并且限制两点之间只有一条路径.费用的计算公式为:所有边的费用之和.而边$x->y$的费用就为:$y$到初 ...

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

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

  6. 牛客题库 题解 | #[NOIP2017]图书管理员#

    链接:#[NOIP2017]图书管理员# 题目牛客网是互联网求职神器,C++.Java.前端.产品.运营技能学习/备考/求职题库,在线进行百度阿里腾讯网易等互联网名企笔试面试模拟考试练习,和牛人一起讨 ...

  7. [NOIp2017 Day2 T3] 列队phalanx(线段树 / 平衡树)

    题目 描述 Sylvia 是一个热爱学习的女♂孩子. 前段时间,Sylvia 参加了学校的军训.众所周知,军训的时候需要站方阵. Sylvia 所在的方阵中有n×mn×mn \times m名学生,方 ...

  8. NOI题库 python题解-2022.01.07整理(1.4-1.7)

    python && C++ NOI编程题解1.4 https://blog.csdn.net/yigezzchengxuyuan/article/details/86651658 ht ...

  9. 简单的题解 属2017

    -- 待补充 P3958 [NOIP2017 提高组] 奶酪 刷过,当时没一次过 因为没看出来是dfs,以及没有交代码前编译 P3959 [NOIP2017 提高组] 宝藏 两次没过,第三次过了,最后 ...

最新文章

  1. 寻找人机之间的中间地带-评述3本人机协作的书
  2. linux查代替命令,Linux下查/删/替 命令(转)
  3. 【mysql分区分表】mysql 按时间分区 【partition】
  4. 评论数据获取、词频统计、词云图
  5. sql server中存储过程提示错误
  6. 医学图像分析相关的会议
  7. Spring中,修改注入的bean名称
  8. IDEA中项目的两种打包方式
  9. IntelliJ IDEA for mac汉化
  10. SVN工具介绍- VisualSVN Server与TortoiseSVN
  11. Office EXCEL 如何保留两位小数,四舍五入
  12. 三十、动名词短语 2
  13. Ubuntu上实现蓝牙串口通讯(SPP)
  14. 关于多卡Android设备获取手机号的研究
  15. 视频编码基础:I帧、P帧 和 B 帧
  16. 近200篇机器学习&amp;深度学习资料分享(含各种文档,视频,源码等)
  17. 小程序|炎炎夏日、清爽一夏、头像大换装
  18. MEM/MBA数学强化(05)应用题
  19. 英语口语学习(13-14)
  20. CAN诊断浅谈 如何用CAN工具进行诊断

热门文章

  1. 爬取豆瓣排行榜电影数据
  2. 我的世界java作弊怎么开_我的世界怎么开作弊模式 开启方法介绍
  3. OSChina 周三乱弹 ——史上最有名的拖延症的患者
  4. The thirteen day
  5. (附源码)ssm高校选课系统 毕业设计 291627
  6. conda.core.subdir_data.Response304ContentUnchanged CondaHTTPError: HTTP 000 CONNECTION FAILED
  7. 商务智能-系统概述-商务智能作用
  8. 最好用的项目流程管理工具 OmniPlan Pro 4.3.2 Mac版(内附安装包链接)
  9. 穷人和富人的思维方式探析
  10. 2019 校内赛 RPG的地牢猎手(bfs+优先队列)