@codeforces - 1056G@ Take Metro


@description@

There are n points on the ring, numbered 1 to n clockwise order. 1 ~ m wherein the dot is red, m + 1 ~ n blue point number.
You start at point s, and given a t.

You need to repeat the following steps until t = 0:
If your location node is red, clockwise movement point t; t otherwise moved counterclockwise points. Then t minus one.

Seeking final where the node numbers.

Input
The first line contains two integers n and m (3≤n≤10 ^ 5, 1≤m < n), meaning supra.
The second line contains two integers s and t (1≤s≤n, 1≤t≤10 ^ 12) , meaning supra.

Output
outputs only an integer representing the node numbers of the final location.

Examples
Input
10 4
3 1
Output
4

Input
10 4
3 5
Output
4

@solution@

Difficult to think when x> n, we take x mod n is equivalent to step (n step equivalent to around a circle).
So we can take advance steps t mod n, left after every n steps (i.e., go n, n - 1, ..., 1 -step) is repeated t / n times.
We can go pretreatment each point n, n - 1, ..., destination reached by one step, and then you can double up.

Next consider how each point pretreated go n, n - 1, ..., 1-step to reach the destination. We dare set up a dp.
If provided with said positive dp state (i.e. defined dp [i] [j] represents a departure from the walking i n, ..., n - destination reached by steps j), we rely on the transfer dp [i] [j -1], not optimized.
So we set up backwards dp state that the definition of dp [i] [j] represents a departure from i go j, ..., destination reached by one step.
Such sub-dp [i] [j] in the i <equals = m dp [i + j] [j-1]; in i> is equal to dp when m [ij] [j-1 ] ( here, ± j is add or subtract the meaning of the ring).

Then we can optimize this dp: the transfer of its attention is always dp [] [j-1] are two intervals pan get dp [] [j].
So we can use persistence treap, each equivalent to first division dp transfer the corresponding interval, and then merge the interval.
There is a small trick: be persistent in depth treap may be more deep, you can try to merge written in merger + random periodic reconstruction (of course, does not have to add ... this depends on the specific person to person).

@accepted code@

#include<cstdio>
#include<cstdlib>
#include<ctime>
#include<iostream>
using namespace std;
typedef long long ll;
const int MAXN = 100000;
struct treap{
    struct node{
        int key, siz;
        node *ch[2];
    }pl[30*MAXN + 5], *ncnt, *NIL;
    typedef pair<node*, node*> Droot;
    treap() {
        NIL = &pl[0];
        NIL->ch[0] = NIL->ch[1] = NIL;
        NIL->key = NIL->siz = 0;
    }
    void trans(int *f, node *x, int k) {
        if( x == NIL ) return ;
        f[x->ch[0]->siz + k + 1] = x->key;
        trans(f, x->ch[0], k);
        trans(f, x->ch[1], x->ch[0]->siz + k + 1);
    }
    void pushup(node *x) {
        x->siz = x->ch[0]->siz + x->ch[1]->siz + 1;
    }
    node *build(int *f, int l, int r) {
        if( l > r ) return NIL;
        int mid = (l + r) >> 1;
        node *p = (++ncnt); p->key = f[mid];
        p->ch[0] = build(f, l, mid - 1);
        p->ch[1] = build(f, mid + 1, r);
        pushup(p);
        return p;
    }
    node *build(int *f, int n) {
        ncnt = &pl[0];
        return build(f, 1, n);
    }
    Droot split(node *x, int k) {
        if( x == NIL ) return make_pair(NIL, NIL);
        node *p = (++ncnt); (*p) = (*x);
        if( x->ch[0]->siz >= k ) {
            Droot q = split(x->ch[0], k);
            p->ch[0] = q.second; pushup(p);
            return make_pair(q.first, p);
        }
        else {
            Droot q = split(x->ch[1], k - x->ch[0]->siz - 1);
            p->ch[1] = q.first; pushup(p);
            return make_pair(p, q.second);
        }
    }//first k elements
    node *merge(node *x, node *y) {
        if( x == NIL ) return y;
        if( y == NIL ) return x;
        node *p = (++ncnt);
        if( rand() & 1 ) {
            (*p) = (*x), p->ch[1] = merge(x->ch[1], y);
            pushup(p);
        }
        else {
            (*p) = (*y), p->ch[0] = merge(x, y->ch[0]);
            pushup(p);
        }
        return p;
    }
}T;
treap::node *root;
int f[MAXN + 5];
int nxt[45][MAXN + 5];
int main() {
    int n, m, s; ll t;
    scanf("%d%d%d%lld", &n, &m, &s, &t);
    srand(20041112 ^ n ^ m ^ s);
    for(int i=1;i<=n;i++) f[i] = i;
    root = T.build(f, n);
    for(int i=1;i<=n;i++) {
        if( i % 300 == 0 )
            T.trans(f, root, 0), root = T.build(f, n);
        treap::node *p, *q;
        treap::node *tmp = T.split(root, i).second;
        if( tmp->siz >= m )
            p = T.split(tmp, m).first;
        else p = T.merge(tmp, T.split(root, m-tmp->siz).first);
        tmp = T.split(root, n - i).first;
        if( tmp->siz >= n-m )
            q = T.split(tmp, tmp->siz-(n-m)).second;
        else q = T.merge(T.split(root, n-((n-m)-tmp->siz)).second, tmp);
        root = T.merge(p, q);
    }
    T.trans(f, root, 0);
    while( t % n ) {
        if( s <= m ) s = (s - 1 + t) % n + 1;
        else s = ((s - 1 - t) % n + n) % n + 1;
        t--;
    }
    for(int i=1;i<=n;i++) nxt[0][i] = f[i];
    for(int j=1;j<45;j++)
        for(int i=1;i<=n;i++)
            nxt[j][i] = nxt[j-1][nxt[j-1][i]];
    int x = t/n;
    for(int i=44;i>=0;i--)
        if( (1LL<<i) & x ) s = nxt[i][s];
    printf("%d\n", s);
}

@details@

Timing reconstruction. . . I feel very show. . .
Of course, this is based on the number of internal nodes treap itself is constant premise.

Because of the timing of the reconstruction of the reason it does not need to consume a particularly large space.

Guess you like

Origin www.cnblogs.com/Tiw-Air-OAO/p/11688924.html