[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 行每行一个整数,分别代表每次修改后的答案。
输入输出样例
说明
【数据范围】
3≤n≤10^5,0≤m≤10^5,0≤T_i/T_x≤10^53≤n≤105,0≤m≤105,0≤Ti/Tx≤105 。
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 }