ディレクトリ
@説明@
「新しい危機がどのように停滞することができ、浮上している」 -あなたは巣⽳少しモンスターを攻撃することを決定しました。
1からnまでの番号⾏モンスターn個の巣を⽳、そこ⼀、i番目の巣⽳防衛ケアは、RIにあります。
⼀(今回⽳X巣が破壊されている)⽳x番目の巣に⽣あなたを開始し、攻撃のケアがRXに取られています。
たびは、3つの動作モードがあります。
- あなたの左の最初のフレームが巣の⽳によって破壊されていない攻撃し、あなたの攻撃のケアはその防衛視力ズームインに等しくなるようにとられている尋ねます。
- あなたが最初のフレームを攻撃しないあなたが世話を攻撃するように要求破壊巣⽳権利は、その防衛視力ズームインに等しくなるようにとられています。
- それはあなたのK操作を取る、あなたの攻撃のケアが取られてい増やし、あなたの攻撃のケアは、(infファイルとして数えない状態で)撮影してきた小さな巣⽳防衛ケアによって破壊されていない最初のフレームの両側となっています。
Exが必要とされるすべての巣⽳最小数をxと破壊したときに、あなたが⽣を作ることを意味します。
今Qが求めている、それぞれが2つの操作を持っています:
- そして巣⽳X X + 1を切り替えます。
- 二つの数xとy、検索所与\(\和^ {Y} _ {i = X} E_i \) の値。
入力
最初のフレーム⾏二つの整数nとk。
セカンドショット⾏のn Riをを表す整数。
後の場合、ドライ⾏(Q走行)、開始⼀OPの数は、操作の種類を表す場合、OP = 1、次⼀番号x。
そうでない場合は、OP = 2、次の2つの数xとy。
出力
ごとに⾏⼀整数は答えを表します。
サンプル入力
5 3
2 3 1 4 1
2 2 2
2 1 5
1 2
2 2 2
2 1 5
の出力例
7
38
13
41
100%N≤10 ^ 5、K≤10 ^ 6は、R≤10 ^ 9、QのEMPTYフルスコア≤2×10 ^ 5、X <N。
@溶液@
例を解決する方法を、与えられたxに対して考えてみましょう。Cは、変更されたセットのパワーは、明らかに実施例= C *とのK +(Nを攻撃 -1)。
だから、与えられたxのへの質問は、どのように何度も攻撃力が変更されました。
ひとつのアイデアは、再帰を介して転送されます。Fに[x]はxが変化し始めるから攻撃の数を表します。
X最初の位置は、次に、pはLMとRmのうち設定され、第一のRx RMの右の位置の数よりも大きいRxのLMの数よりも大きい見つけること左が箇所の少ない数に相当します。
従ってF [X] = F [pの ] + 1。
もう一つのアイデアは、別の番号に番号の寄与を考慮することです。以上の数yに等しいxの右側に最初のものを見つけ、Xを考えます。
その後、xとyの間の数のために、彼らは確かにこの場所xの攻撃力を変更する必要があります。寄与を生成するために、xとyの間の数xのように。
ただし、のRx = Ryの時間ならば、忘れてしまう上記算出方法によれば、R yは受信一度計算を繰り返します。しかし、実際にはRxおよびRyが同じ攻撃の変化です。特殊な文にそう。
メンテナンスを変更する方法を検討するとき。X及びX + 1を交換した場合、R [X]> R [X作成することを望むかもしれない + 1]( 共感のその逆)。
基本的なXで見つけることができるかについては変更されません。X + 1のために、我々は最初の新しい例の再発を通してそれを見つけます。そして、影響範囲のツリーラインを通してそれを修正します。
バイナリOの我々は、RXラインツリー多数(^ 2ログ)は、以前のX / X最も近い比もでき後に得られました。
どのようにコードを参照することができ、特定の動作を実現します。
小さなディテール:完全に上記に従って実現した場合は、最寄りのxのRxを見つけること以上を達成するためにRxのxよりも大きいだけでなく、両方を達成するための線分にツリーに最も近いを見つける必要があります。
同等のケースでは、我々はリストを維持可能性がある、元に最も近い同等のは、x /後のRx、簡単なメンテナンスクリックの交換を接続します。
@acceptedコード@
#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);
}
}
}
}
@詳細@
思考、アプリケーションセグメントツリー、中程度の量は、典型的なタイトルバーとしてみなされます。
よりだけ大きい、等しい、等より少ないために幾分困難な議論。