@NOI analog 2017.07.02 - T1 @ Attack


@description@

"The new crisis has emerged, how can stagnation" - you decide to attack the nest ⽳ little monster.
There ⼀ ⾏ monster n nests ⽳, numbered from 1 to n, the i-th nest ⽳ defense care has to Ri.
⼀ start you down ⽣ in the x-th nest ⽳ (this time ⽳ x nest has been destroyed), attack care has been taken to Rx.

Every time you have three modes of operation:

  1. Attack your left first frame has not been destroyed by a nest ⽳, ask your attack care has been taken to be equal to its zoomed in defense eyesight.
  2. You do not attack the first frame a destroyed nest ⽳ the right, asks you to attack care has been taken to be equal to its zoomed in defense eyesight.
  3. Increase your attack care has been taken, it will take you K operations, your attack care has become a both sides of the first frame has not been destroyed by the smaller nest ⽳ defense care has been taken (in the absence counted as inf).

Ex mean that you make a ⽣ when x and destroy all nests ⽳ minimum number required.

There are now asking the Q, each have two operations:

  1. And switching nest ⽳ x x + 1.
  2. Given two numbers x and y, find \ (\ sum ^ {y} _ {i = x} E_i \) values.

input
first frame ⾏ two integers n and k.
Second shot ⾏ n integers representing Ri.
If after, dry ⾏ (q running), the number of starts ⼀ op represents the type of operation, if the op = 1, the next ⼀ number x.
Otherwise op = 2, the next two numbers x and y.

output
per ⾏ ⼀ integers represent the answer.

sample input
5 3
2 3 1 4 1
2 2 2
2 1 5
1 2
2 2 2
2 1 5
sample output
7
38
13
41

EMPTY full score of 100% n ≤ 10 ^ 5, k ≤ 10 ^ 6, Ri ≤ 10 ^ 9, q ≤ 2 * 10 ^ 5, x <n.

@solution@

Consider for a given x, how to solve Ex. C attacks the changed set power, then clearly Ex = c * k + (n -1).
So the question into for a given x, how many times has changed the offensive power.

One idea is transferred through recursive. So f [x] x represents the number of attack from the start to change.
X left to find the first location is larger than the Rx lm number, larger than the right of the first Rx rm its position number, then p is set among lm and rm corresponds to a smaller number of locations.
Thus with f [x] = f [p ] + 1.

Another idea is to consider the contribution of a number to another number. Consider x, find the first one to the right of x greater than or equal to its number y.
Then for a number between x and y, they will certainly have to change the attack force x this place. So for a number x between x and y to generate contributions.
Note, however, if Rx = Ry time, according to the above calculation method will forget a, Ry repeated calculations once Rx. But in fact Rx and Ry is a change in the same attack. So to special sentence.

When considering how to modify maintenance. If the exchange of x and x + 1, may wish to make R [x]> R [x + 1] ( empathy vice versa).
For what can be found in basic x does not change. For x + 1, we first find it through the new Ex recurrence. And then modify it through the tree line on the affected range.
We Rx line tree large number of binary O (log ^ 2) obtained previously x / x after the closest ratio can also.
How to achieve the specific operation may reference code.

A small detail: If fully realized in accordance with the above, you need to find the line segment closest to the tree to achieve both greater than x Rx but also to achieve greater than or equal to find the nearest x Rx.
In the case of equal, we might maintain a list, the closest equivalent to the former will connect Rx x / after, when the exchange of simple maintenance click.

@accepted code@

#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
const int MAXN = 100000;
int R[MAXN + 5];
struct segtree {
    struct node{
        int mx, le, ri;
        int tag; ll sum;
    }t[4*MAXN + 5];
    void pushup(int x) {
        t[x].mx = (R[t[x<<1].mx] > R[t[x<<1|1].mx]) ? t[x<<1].mx : t[x<<1|1].mx;
        t[x].sum = t[x<<1].sum + t[x<<1|1].sum;
    }
    void build(int x, int l, int r) {
        t[x].le = l, t[x].ri = r, t[x].tag = t[x].sum = 0;
        if( l == r ) {
            t[x].mx = l;
            return ;
        }
        int mid = (l + r) >> 1;
        build(x<<1, l, mid);
        build(x<<1|1, mid+1, r);
        pushup(x);
    }
    void pushdown(int x) {
        if( t[x].tag ) {
            t[x<<1].tag += t[x].tag, t[x<<1].sum += t[x].tag*(t[x<<1].ri-t[x<<1].le+1);
            t[x<<1|1].tag += t[x].tag, t[x<<1|1].sum += t[x].tag*(t[x<<1|1].ri-t[x<<1|1].le+1);
            t[x].tag = 0;
        }
    }
    void add(int x, int l, int r, int d) {
        if( l > t[x].ri || r < t[x].le )
            return ;
        if( l <= t[x].le && t[x].ri <= r ) {
            t[x].tag += d;
            t[x].sum += d*(t[x].ri-t[x].le+1);
            return ;
        }
        pushdown(x);
        add(x<<1, l, r, d), add(x<<1|1, l, r, d);
        pushup(x);
    }
    void update(int x, int p) {
        if( p > t[x].ri || p < t[x].le )
            return ;
        if( t[x].le == t[x].ri )
            return ;
        pushdown(x);
        update(x<<1, p), update(x<<1|1, p);
        pushup(x);
    }
    int query_mx(int x, int p, int type) {
        if( t[x].le == t[x].ri )
            return (R[t[x].le] > R[p]) ? t[x].le : -1;
        pushdown(x);
        if( type ) {
            if( p >= t[x<<1].ri )
                return query_mx(x<<1|1, p, type);
            else if( p < t[x<<1].le ) {
                if( R[t[x].mx] <= R[p] ) return -1;
                else return (R[t[x<<1].mx] > R[p]) ? query_mx(x<<1, p, type) : query_mx(x<<1|1, p, type);
            }
            else {
                int q = query_mx(x<<1, p, type);
                if( q == -1 ) return query_mx(x<<1|1, p, type);
                else return q;
            }
        }
        else {
            if( p <= t[x<<1|1].le )
                return query_mx(x<<1, p, type);
            else if( p > t[x<<1|1].ri ) {
                if( R[t[x].mx] <= R[p] ) return -1;
                else return (R[t[x<<1|1].mx] > R[p]) ? query_mx(x<<1|1, p, type) : query_mx(x<<1, p, type);
            }
            else {
                int q = query_mx(x<<1|1, p, type);
                if( q == -1 ) return query_mx(x<<1, p, type);
                else return q;
            }
        }
    }
    int query_sum(int x, int l, int r) {
        if( l > t[x].ri || r < t[x].le )
            return 0;
        if( l <= t[x].le && t[x].ri <= r )
            return t[x].sum;
        pushdown(x);
        return query_sum(x<<1, l, r) + query_sum(x<<1|1, l, r);
    }
}T;
int d[MAXN + 5], lst[MAXN + 5], nxt[MAXN + 5], adj[MAXN + 5];
int main() {
    freopen("attack.in", "r", stdin);
    freopen("attack.out", "w", stdout);
    int n, k; scanf("%d%d", &n, &k);
    for(int i=1;i<=n;i++)
        scanf("%d", &R[i]), d[i] = R[i];
    sort(d + 1, d + n + 1);
    int dsiz = unique(d + 1, d + n + 1) - d - 1;
    for(int i=1;i<=n;i++)
        R[i] = lower_bound(d + 1, d + dsiz + 1, R[i]) - d;
    R[0] = R[n+1] = dsiz + 1;
    for(int i=1;i<=dsiz;i++)
        adj[i] = n + 1;
    for(int i=n;i>=1;i--) {
        nxt[i] = adj[R[i]];
        lst[adj[R[i]]] = i;
        adj[R[i]] = i;
    }
    for(int i=1;i<=dsiz;i++)
        lst[adj[i]] = 0;
    T.build(1, 0, n+1);
    for(int i=1;i<=n;i++) {
        int x = T.query_mx(1, i, 0), y = T.query_mx(1, i, 1);
        if( x >= lst[i] )
            T.add(1, x + 1, i - 1, 1);
        if( y <= nxt[i] )
            T.add(1, i + 1, y - 1, 1);
        else T.add(1, i + 1, nxt[i] - 1, 1);
    }
    int op;
    while( scanf("%d", &op) == 1 ) {
        if( op == 2 ) {
            int l, r; scanf("%d%d", &l, &r);
            printf("%lld\n", 1LL*k*T.query_sum(1, l, r) + 1LL*(n-1)*(r-l+1));
        }
        else {
            int x, y; scanf("%d", &x); y = x + 1;
            if( R[x] == R[y] ) continue;
            if( R[x] > R[y] ) {
                int p = T.query_mx(1, y, 1);
                if( p <= nxt[y] )
                    T.add(1, y + 1, p - 1, -1);
                int xs = T.query_sum(1, x, x), ys = T.query_sum(1, y, y); 
                T.add(1, x, x, -xs), T.add(1, y, y, xs-ys);
                swap(R[x], R[y]), T.update(1, x), T.update(1, y);
                swap(nxt[x], nxt[y]), swap(lst[x], lst[y]);
                lst[nxt[x]] = nxt[lst[x]] = x;
                lst[nxt[y]] = nxt[lst[y]] = y;
                int q = T.query_mx(1, x, 0);
                T.add(1, x, x, R[q] > R[y] ? T.query_sum(1, y, y) + 1 : T.query_sum(1, q, q) + 1);
                if( q >= lst[x] )
                    T.add(1, q + 1, x - 1, 1);
            }
            else {
                int p = T.query_mx(1, x, 0);
                if( p >= lst[x] )
                    T.add(1, p + 1, x - 1, -1);
                int xs = T.query_sum(1, x, x), ys = T.query_sum(1, y, y); 
                T.add(1, x, x, ys-xs), T.add(1, y, y, -ys);
                swap(R[x], R[y]), T.update(1, x), T.update(1, y);
                swap(nxt[x], nxt[y]), swap(lst[x], lst[y]);
                lst[nxt[x]] = nxt[lst[x]] = x;
                lst[nxt[y]] = nxt[lst[y]] = y;
                int q = T.query_mx(1, y, 1);
                T.add(1, y, y, R[q] > R[x] ? T.query_sum(1, x, x) + 1 : T.query_sum(1, q, q) + 1);
                if( q <= nxt[y] )
                    T.add(1, y + 1, q - 1, 1);
            }
        }
    }
}

@details@

A moderate amount of thinking, the application segment tree, be regarded as typical title bar.
For less than just greater than, equal to, etc. discussed somewhat daunting.

Guess you like

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