蒟蒻被卡了很久…………
I. 題意:
一個長度爲坑爹的是,在計算子序列的和時,相同的數只會被計算一次(舉個例子,即
II. 題解:
1. 先看一個簡單的情況:
如果沒有“相同的數只會被計算一次”這個限制條件,我們應該怎麼做?
方法一:暴力枚舉,時間複雜度
方法二:貪心,時間複雜度
顯然以上兩種方法都不行。我們考慮以下做法:
設
顯然,我們可以從
優化1:注意到在一次詢問
優化2:注意到在多組詢問中有很多重複計算的部分。依次處理
2. 那這道題呢:
考慮到剛纔那種做法如果照搬會造成的問題:相同數字被算了幾次。對於一個數
III. 代碼走起
(不要隨便看代碼。不要隨便看代碼。不要隨便看代碼。重要的事情說三遍。 )
(代碼細節自己推敲,或者看類似的題的題解。類似這樣要求維護歷史最值的線段樹題目不少。)
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
//Global Variables & Definitions
int max(int a, int b) { return a > b ? a : b; }
int min(int a, int b) { return a < b ? a : b; }
#define MS(arr, x) memset(arr, x, sizeof(arr))
#define MAXN 100010
#define MAXQ 100010
#define MAXV 100010
int N, Q;
int A[MAXN];
struct Query {
int I; //Index
int X, Y;
} Qs[MAXQ];
bool QCompY(Query a, Query b) { return a.Y < b.Y; }
bool QCompI(Query a, Query b) { return a.I < b.I; }
int _P[MAXV * 2]; //P[i]: last place i appeared
int *P;
int ans[MAXN];
//End Global Variables & Definitions
//Segment Tree
#define DEFINE_MID int mid = (l + r) >> 1
#define lson ((u) << 1)
#define rson ((u) << 1 | 1)
#define MAXT (MAXN << 2)
int m[MAXT];
int hm[MAXT];
int lazy[MAXT], hmlazy[MAXT];
void PushUp(int u) {
m[u] = max(m[lson], m[rson]);
hm[u] = max(hm[lson], hm[rson]);
hm[u] = max(hm[u], m[u]);
}
void PushDown(int u) {
if(!(lazy[u] | hmlazy[u])) return;
hmlazy[lson] = max(hmlazy[lson], lazy[lson] + hmlazy[u]);
hmlazy[rson] = max(hmlazy[rson], lazy[rson] + hmlazy[u]);
hm[lson] = max(hm[lson], m[lson] + hmlazy[u]);
hm[rson] = max(hm[rson], m[rson] + hmlazy[u]);
lazy[lson] += lazy[u];
lazy[rson] += lazy[u];
m[lson] += lazy[u];
m[rson] += lazy[u];
lazy[u] = hmlazy[u] = 0;
}
void MakeLazy(int u, int v) {
lazy[u] += v;
m[u] += v;
hmlazy[u] = max(hmlazy[u], lazy[u]);
hm[u] = max(hm[u], m[u]);
}
void Build(int u, int l, int r) {
//m[u] = hm[u] = lazy[u] = hmlazy[u] = 0;
if(l == r) return;
DEFINE_MID;
Build(lson, l, mid);
Build(rson, mid + 1, r);
}
void Add(int u, int l, int r, int L, int R, int v) {
if(L <= l && R >= r) {
MakeLazy(u, v); return;
}
PushDown(u);
DEFINE_MID;
if(L <= mid) Add(lson, l, mid, L, R, v);
if(R > mid) Add(rson, mid + 1, r, L, R, v);
PushUp(u);
}
int Query(int u, int l, int r, int L, int R) { //Query historical maximum in [L, R]
if(L <= l && R >= r) {
return hm[u];
}
PushDown(u);
DEFINE_MID;
int temp = -1;
if(L <= mid) temp = max(temp, Query(lson, l, mid, L, R));
if(R > mid) temp = max(temp, Query(rson, mid + 1, r, L, R));
return temp;
}
//End Segment Tree
//Main Structure
inline void Deal(int v, int p) {
Add(1, 1, N, P[v] + 1, p, v);
P[v] = p;
}
inline void ir() {
//MS(_P, 0);
P = _P + MAXV;
//Read
scanf("%d", &N);
for(int i = 1;i <= N;++i) scanf("%d", &A[i]);
scanf("%d", &Q);
for(int i = 0;i < Q;++i) {
scanf("%d%d", &Qs[i].X, &Qs[i].Y);
Qs[i].I = i;
}
sort(Qs, Qs + Q, QCompY);
Build(1, 1, N);
}
int main() {
ir();
int ptr = 0; //The last one dealed
for(int i = 0;i < Q;++i) {
int TX = Qs[i].X, TY = Qs[i].Y;
while(ptr < TY) {
++ptr;
Deal(A[ptr], ptr);
}
//Qs[i].X = Query(1, 1, N, TX, TY);
ans[Qs[i].I] = Query(1, 1, N, TX, TY);
}
//sort(Qs, Qs + Q, QCompI);
//for(int i = 0;i < Q;++i) printf("%d\n", Qs[i].X);
for(int i = 0;i < Q;++i) printf("%d\n", ans[i]);
return 0;
}