【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('
')
#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();
}
原文地址:https://www.cnblogs.com/ivorysi/p/9975265.html