[HNOI/AHOI2018]转盘

题目描述

一次小G和小H准备去聚餐,但是由于太麻烦了于是题面简化如下:

一个转盘上有摆成一圈的 nn 个物品(编号1~ nn ),其中的 ii 个物品会在 T_iTi 时刻出现。

在0时刻时,小G可以任选 nn 个物品中的一个,我们将其编号为 s_0s0 。并且如果 ii 时刻选择了物品 s_isi ,那么 i+1i+1 时刻可以继续选择当前物品或选择下一个物品。当 s_isi 为 nn 时,下一个物品为物品 11 ,否则为物品 s_{i}+1si+1 。在每一时刻(包括0时刻),如果小G选择的物品已经出现了,那么小G将会标记它。小H想知道,在物品选择的最优策略下,小G什么时候能标记所有物品?

但麻烦的是,物品的出现时间会不时修改。我们将其描述为 mm 次修改,每次修改将改变其中一个物品的出现时间。每次修改后,你也需求出当前局面的答案。对于其中部分测试点,小H还追加了强制在线的要求。

输入输出格式

输入格式:

 

第一行三个非负整数 nn 、 mm 、 pp ,代表一共有 nn 个物品, mm 次修改。 pp 只有0或1两种取值,强制在线时 pp 为1,否则 pp 为0.

接下来一行,有 nn 个非负整数,第 ii 个数 T_iTi 代表物品 ii 的出现时间。

接下来 mm 行,每行两个非负整数 xx 、 yy ,代表一次修改及询问。修改方式如下:

(1)如果 p=0p=0 ,则表示物品 xx 的出现时间 T_xTx 修改为 yy 。

(2)如果 p=1p=1 ,在先将 xx 和 yy 分别异或 LastAnsLastAns ,得到 x'x′ 和 y'y′ ,然后将物品 x'x′ 的出现时间 T_{x'}Tx 修改为 y'y′。其中的 LastAnsLastAns 是前一个询问的结果;特别的,第一次修改时 LastAnsLastAns 为初始局面的答案。

保证输入合法。

 

输出格式:

 

第一行一个整数,代表初始局面的答案。

接下来 mm 行每行一个整数,分别代表每次修改后的答案。

 

输入输出样例

输入样例#1: 复制
5 3 0
1 2 3 4 5
3 5
5 0
1 4
输出样例#1: 复制
5
7
6
7

说明

【数据范围】

3≤n≤10^5,0≤m≤10^5,0≤T_i/T_x≤10^53n105,0m105,0Ti/Tx105 。

传送门

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cmath>
 5 #include<cstring>
 6 using namespace std;
 7 int val[800001],Max[800001],a[800001],n,m,p,t[800001],ans;
 8 int query(int rt,int l,int r,int Mx)
 9 {
10   if (l==r)
11     {
12       return l+max(Mx,Max[rt]);
13     }
14   int mid=(l+r)/2;
15   if (Mx<=Max[rt<<1|1])
16     return min(val[rt],query(rt<<1|1,mid+1,r,Mx));
17   else return min(mid+Mx+1,query(rt<<1,l,mid,Mx));
18 }
19 void pushup(int rt,int l,int r)
20 {
21   int mid=(l+r)/2;
22   val[rt]=query(rt<<1,l,mid,Max[rt<<1|1]);
23   Max[rt]=max(Max[rt<<1],Max[rt<<1|1]);
24 }
25 void update(int rt,int l,int r,int x)
26 {
27   if (l==r)
28     {
29       Max[rt]=a[l];
30       val[rt]=a[l]+l;
31       return;
32     }
33   int mid=(l+r)/2;
34   if (x<=mid) update(rt<<1,l,mid,x);
35   else update(rt<<1|1,mid+1,r,x);
36   pushup(rt,l,r);
37 }
38 void build(int rt,int l,int r)
39 {
40   if (l==r)
41     {
42       Max[rt]=a[l];
43       val[rt]=a[l]+l;
44       return;
45     }
46   int mid=(l+r)/2;
47   build(rt<<1,l,mid);
48   build(rt<<1|1,mid+1,r);
49   pushup(rt,l,r);
50 }
51 int main()
52 {int i,x,y;
53   cin>>n>>m>>p;
54   for (i=1;i<=n;i++)
55     {
56       scanf("%d",&t[i]);
57       a[i]=t[i]-i;
58       a[n+i]=t[i]-n-i;
59     }
60   build(1,1,n<<1);
61   ans=val[1]+n-1;
62   printf("%d\n",ans);
63   for (i=1;i<=m;i++)
64     {
65       scanf("%d%d",&x,&y);
66       x^=ans*p;y^=ans*p;
67       t[x]=y;
68       a[x]=t[x]-x;
69       a[n+x]=t[x]-n-x;
70       update(1,1,n<<1,x);
71       update(1,1,n<<1,n+x);
72       ans=val[1]+n-1;
73       printf("%d\n",ans);
74     }
75 }

 

posted @ 2018-04-27 19:49  Z-Y-Y-S  阅读(457)  评论(0编辑  收藏  举报