table of Contents
@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:
- 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.
- 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.
- 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:
- And switching nest ⽳ x x + 1.
- 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.