Registra principalmente el preprocesamiento, O1 toma la suma de prefijos de cualquier suma de prefijos de intervalo
tema
6077. El poder total del mago y
ideas para resolver problemas
Greedy considera de pequeño a grande, cada cálculo se basa en ai a_iayoContribución como mínimo.
Veamos ejemplos específicos:
- Considere un 2 a_2a2
Contribución al intervalo mínimo [ 1 , 2 ] , [ 1 , 3 ] , [ 1 , 4 ] , [ 1 , 5 ] , [ 2 , 2 ] , [ 2 , 3 ] , [ 2 , 4 ] , [ 2 , 5 ] [1,2],[1,3],[1,4],[1,5],[2,2],[2,3],[2,4],[2,5] ][ 1 ,2 ] ,[ 1 ,3 ] ,[ 1 ,4 ] ,[ 1 ,5 ] ,[ 2 ,2 ] ,[ 2 ,3 ] ,[ 2 ,4 ] ,[ 2 ,5 ] - Considere un 4 a_4a4
Contribución al intervalo mínimo [ 3 , 4 ] , [ 4 , 4 ] , [ 4 , 5 ] , [ 3 , 5 ] [3,4],[4,4],[4,5],[3 ,5][ 3 ,4 ] ,[ 4 ,4 ] ,[ 4 ,5 ] ,[ 3 ,5 ]
Si calculamos el intervalo[1,4][1,4][ 1 ,4 ] o[2, 4] [2,4][ 2 ,4 ] , luego se repite el cálculo de la contribución en 1. Por lo tanto, cada cálculode ai a_iayoCuando la contribución, el punto final izquierdo no supera el valor anterior y ai a_iayomisma posición, punto final derecho a nnn , pero esto no es suficiente, también debemos asegurarnos de que el valor mínimo de estos intervalos seaai a_iayo。 - Considere un 3 a_3a3Contribución a
intervalo mínimo [ 3 , 3 ] [3,3][ 3 ,3 ] legal, porque los anteriormente enumeradosai a_iayoson menores que el valor actual, la matriz se dividirá.
A continuación, considere cómo calcular la contribución del intervalo. Es imposible para nosotros enumerar todos los intervalos, por lo que habrá tiempo para observar la contribución en el paso 1 anterior.
fácil de detectar, con ai a_iayoCuando es el valor mínimo, los tiempos de contribución del elemento izquierdo son 1 vez, 2 veces, 3 veces. . . . . . 1 vez, 2 veces, 3 veces... ...1 vez _2 veces ,3 veces . . . . . , el número de contribuciones del elemento izquierdo es. . . . . 3 veces, 2 veces, 1 vez... ...3 veces, 2 veces, 1 vez. . . . . 3 veces , _2 veces ,primaria , aia_iayoEl número de contribuciones por sí solo es ( numleft + 1 ) × ( numright + 1 ) (num_{left}+1)\times(num_{right}+1)( núm _ _izquierda _ _ _+1 )×( núm _ _correcto _ _ _ _+1 ) veces. Solo necesita determinar los puntos finales izquierdo y derecho del intervalo, puede calcular directamenteel ai a_iayoContribución de todos los intervalos para el mínimo.
ai a_iayoEl número de contribuciones en ambos lados satisface la ley de suma de prefijos de la suma de prefijos . La parte derecha es la suma de prefijos de las sumas de prefijos de izquierda a derecha. La parte izquierda es la suma de sufijos de la suma de sufijos de derecha a izquierda. ¿Cómo calcular rápidamente la suma del prefijo de la suma del prefijo de cualquier intervalo?
Mira la foto de abajo.
Inicialización: s 0 = ss 0 = 0 s_0 = ss_0=0s0=s s0=0
prearmonización:si = si − 1 + ai s_i = s_{i-1}+a_isyo=syo − 1+ayo
Suma de prefijos de sumas de prefijos: ssi = ssi − 1 + si ss_i = ss_{i-1}+s_is syo=s syo − 1+syo
en conclusión:
ssl , r = ssr − ssl − 1 − ( r − l + 1 ) × sl − 1 ss_{l,r}=ss_{r}-ss_{l-1}-(r-l+1)\times_ {l-1}s sl , r=s sr−s sl − 1−( r−yo+1 )×sl − 1
Es fácil verificar la corrección de la conclusión, así que no la repetiré aquí.
De esta forma, podemos O ( n ) O(n)Después del preprocesamiento O ( n ) ,O ( 1 ) O(1)O ( 1 ) para obtener la suma del prefijo dede cualquier intervalo.
El sufijo es el mismo.
código de CA
const long long N = 1e5 + 5;
const long long mod = 1e9 + 7;
class Solution
{
public:
map<long long, vector<long long>> pos;
long long pre[N], suf[N], ppre[N], ssuf[N];
set<long long> st;
set<long long> vis;
long long n;
void init_ss(vector<int> &a)
{
int n = a.size() - 1;
for (int i = 1; i <= n; i++)
pre[i] = pre[i - 1] + a[i];
for (int i = 1; i <= n; i++)
ppre[i] = (ppre[i - 1] + pre[i]) % mod;
for (int i = n; i >= 1; i--)
suf[i] = suf[i + 1] + a[i];
for (int i = n; i >= 1; i--)
ssuf[i] = (ssuf[i + 1] + suf[i]) % mod;
}
long long getlr(int l, int r)
{
long long len = r - l + 1;
return (ppre[r] - (ppre[l - 1] + pre[l - 1] * len) % mod + mod) % mod;
}
long long getrl(int r, int l)
{
long long len = r - l + 1;
return (ssuf[l] - (ssuf[r + 1] + suf[r + 1] * len) % mod + mod) % mod;
}
long long totalStrength(vector<int> &a)
{
n = a.size();
a.insert(a.begin(), -1);
init_ss(a);
vis.insert(0);
vis.insert(n + 1);
for (long long i = 1; i <= n; i++)
{
st.insert(a[i]);
pos[a[i]].emplace_back(i);
}
long long ans = 0;
for (auto val : st)
{
long long m = pos[val].size();
for (long long i = 0; i < m; i++)
{
long long p = pos[val][i];
auto iter = vis.upper_bound(p);
long long rr = (*iter) - 1;
iter--;
long long ll = (*iter) + 1;
long long lenL = p - ll + 1;
long long lenR = rr - p + 1;
long long num, v;
num = lenL;
v = getlr(p, rr);
ans = (ans + num * v % mod * val) % mod;
num = lenR;
v = getrl(p, ll);
ans = (ans + num * v % mod * val) % mod;
num = lenR * lenL % mod;
v = val;
ans = (ans - num * v % mod * val % mod + mod) % mod; //减去重复贡献
vis.insert(p);
}
}
return ans;
}
};