【LOJ】#2495. 「AHOI / HNOI2018」转盘

题面

题解

考虑我肯定是从一个人出发,开始依次标记,而不会跳过某个人,因为如果我跳过了,那么我之后回来还需要标记它,比不上我等完它再一直走到最后(因为多了走一圈之后走回它的代价)

我们倍长整个序列,我们要求的就是
\(Min_{i = 1}^{n}{Max_{j = i}^{i + n - 1}{T_j - j + i + N - 1}}\)
显然\(j\)越大这个值越小,那么又可以转化成
\(Min_{i = 1}^{n}{Max_{j = i}^{2n}{T_j - j + i + N - 1}}\)
\(A_i = T_i - i\)
那么我们要求的就是
\(Min_{i = 1}^{n}{Max_{j = i}^{2n}{A_j} + i} + N - 1\)
我们考虑维护一个\(MAXV\)\(A_i\)的区间最大值,一个\(VAL\)为这个区间\(Min_{i = L}^{Mid} {Max_{j = i}^{R}{A_j} + i}\)
然后\(Query(u,v)\)表示查询\(u\)这个区间的答案,后面区间的最大值是\(v\)
如果\(v <= MAXV_{rc}\)那么这个区间维护的\(VAL\)就是左区间的值,到右区间继续查找即可
否则右区间的最小贡献就是\(mid + 1 + v\),然后递归到左区间去查即可

代码

#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define space putchar(' ')
#define enter putchar('\n')
#define mp make_pair
#define MAXN 100005
#define pb push_back
//#define ivorysi
using namespace std;
typedef long long int64;
typedef unsigned int u32;
template<class T>
void read(T &res) {
    res = 0;char c = getchar();T f = 1;
    while(c < '0' || c > '9') {
    	if(c == '-') f = -1;
    	c = getchar();
    }
    while(c >= '0' && c <= '9') {
    	res = res * 10 + c - '0';
    	c = getchar();
    }
    res *= f;
}
template<class T>
void out(T x) {
    if(x < 0) {putchar('-');x = -x;}
    if(x >= 10) {
    	out(x / 10);
    }
    putchar('0' + x % 10);
}
int N,M,P;
int a[MAXN * 2];
multiset<int> S;
struct node {
    int L,R,val,maxv;
}tr[MAXN * 4];
void update(int u);
void build(int u,int l,int r);
int Query(int u,int suf);
void build(int u,int l,int r) {
    tr[u].L = l;tr[u].R = r;
    if(l == r) {
        tr[u].maxv = a[l];
        tr[u].val = a[l] + l;
        return ;
    }
    int mid = (l + r) >> 1;
    build(u << 1,l,mid);
    build(u << 1 | 1,mid + 1,r);
    update(u);
}
void update(int u) {
    tr[u].maxv = max(tr[u << 1].maxv,tr[u << 1 | 1].maxv);
    tr[u].val = Query(u << 1,tr[u << 1 | 1].maxv);
}
int Query(int u,int suf) {
    if(tr[u].L == tr[u].R) return tr[u].L + max(tr[u].maxv,suf);
    int mid = (tr[u].L + tr[u].R) >> 1;
    if(suf <= tr[u << 1 | 1].maxv) return min(tr[u].val,Query(u << 1 | 1,suf));
    else return min(mid + 1 + suf,Query(u << 1,suf));
}
void Change(int u,int pos) {
    if(tr[u].L == tr[u].R) {
        tr[u].val = a[pos] + pos;
        tr[u].maxv = a[pos];
        return;
    }
    int mid = (tr[u].L + tr[u].R) >> 1;
    if(pos <= mid) Change(u << 1,pos);
    else Change(u << 1 | 1,pos);
    update(u);
}
void Init() {
    read(N);read(M);read(P);
    for(int i = 1 ; i <= N ; ++i) {
        read(a[i]);a[i + N] = a[i];
        a[i] -= i;a[i + N] -= i + N;
        S.insert(a[i + N]);
    }
    build(1,1,N);
}
void Solve() {
    int lastans = Query(1,*(--S.end())) + N - 1;
    int x,y;
    out(lastans);enter;
    for(int i = 1 ; i <= M ; ++i) {
        read(x);read(y);
        if(P) {x ^= lastans;y ^= lastans;}
        a[x] = y - x;
        S.erase(S.find(a[x + N]));
        a[x + N] = y - x - N;
        S.insert(a[x + N]);
        Change(1,x);
        lastans = Query(1,*(--S.end())) + N - 1;
        out(lastans);enter;
    }
}
int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    Init();
    Solve();
}
posted @ 2018-11-17 19:40  sigongzi  阅读(274)  评论(0编辑  收藏  举报