5286: [Hnoi2018]转盘

5286: [Hnoi2018]转盘

链接

分析:

  $\min\limits_{i=1}^n \{ \max\limits_{j=i}^{i + n - 1} \{ a_{j}+i \} \} +n-1$

  $\min\limits_{i=1}^n \{ \max\limits_{j=i}^{2n} \{ a_{j}+i \} \} +n-1$

  然后线段树,每个区间维护两个值$mx[rt]=\max\limits_{i=l}^{r} a_i,\ $$ans[rt] = \max\limits_{i=l}^{mid}\{ \max\limits_{j = l} ^ {r} {a_j + i} \}$,那么答案是ans[1]。

  考虑如何合并: 两个区间合并到一起,右区间会对左区间的左右点产生影响。即如果右区间的最大值可以去贡献给左区间的某个点,可以递归修改。复杂度$logn$,加上线段树复杂度,总复杂度$O(nlog^2n)$

代码:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<iostream>
#include<cctype>
#include<set>
#include<vector>
#include<queue>
#include<map>
#define fi(s) freopen(s,"r",stdin);
#define fo(s) freopen(s,"w",stdout);
#define Root 1, n << 1, 1
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
using namespace std;
typedef long long LL;

inline int read() {
    int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
    for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
}

const int N = 200005;
int a[N], T[N], mx[N << 2], ans[N << 2];

int Merge(int l,int r,int rt,int x) {
    if (l == r) return l + max(mx[rt], x);
    int mid = (l + r) >> 1;
    if (mx[rt << 1 | 1] >= x) return min(ans[rt], Merge(rson, x));
    else return min(Merge(lson, x), mid + 1 + x);
}
void pushup(int l,int r,int rt) {
    mx[rt] = max(mx[rt << 1], mx[rt << 1 | 1]);
    ans[rt] = Merge(l, (l + r) >> 1, rt << 1, mx[rt << 1 | 1]);
}
void build(int l,int r,int rt) {
    if (l == r) { mx[rt] = a[l], ans[rt] = T[l]; return ; }
    int mid = (l + r) >> 1;
    build(lson); build(rson);
    pushup(l, r, rt);
}
void update(int l,int r,int rt,int p) {
    if (l == r) { mx[rt] = a[l], ans[rt] = T[l]; return ; }
    int mid = (l + r) >> 1;
    if (p <= mid) update(lson, p);
    else update(rson, p);
    pushup(l, r, rt);
}
int main() {
    int n = read(), m = read(), p = read();
    for (int i = 1; i <= n; ++i) {
        T[i] = T[i + n] = read();
        a[i] = T[i] - i, a[i + n] = T[i + n] - i - n;
    }
    build(Root);
    int lastans = ans[1] + n - 1; 
    printf("%d\n", lastans);
    while (m --) {
        int x = read(), y = read();
        if (p) x ^= lastans, y ^= lastans;
        T[x] = T[x + n] = y; a[x] = y - x, a[x + n] = y - x - n;
        update(Root, x); update(Root, x + n);
        lastans = ans[1] + n - 1;
        printf("%d\n", lastans);
    }
    return 0;
}

 

posted @ 2019-02-22 17:32  MJT12044  阅读(167)  评论(0编辑  收藏  举报