Voir le titre original Luo Valley ( https://www.luogu.org/problem/show?pid=2827 )
En fait, cette question des caractéristiques des données écrites en détail pense personnellement que cette question même de la violence pure peut également obtenir 25 points. Ici , le segment I pour expliquer les points à cette question:
[25 min]
Nous examinons d' abord le point de données dans la plage de 1.2.3 m = 0 on trouve des données directement sortie par sujet comme manière, 4,6 points n = 1 simulation de violence aussi directe comme, faire le code spécifique mente pas ......
[65-85 minutes]
notre première pensée est de maintenir la longueur du tas tous les vers de terre, comment ça marche: chaque fois que nous avons retiré du tas le plus long ver de terre, l' a mis dans le tas après la coupe.
Se pose alors la question: chaque fois que nous faisons comment la longueur des autres vers de terre lombrics augmenter q?
Nous pouvons le faire, avec un enregistrement en cours de chaque Ajouter à des vers de terre devrait augmenter la durée du temps d'expliquer quand nous sommes arrivés à la fin de toute coupe m, puis théoriquement tous les vers de terre ont augmenté Ajouter = q * m de longueur. Mais quand nous avons besoin de découper un ver de terre, vers de terre longueur de cette augmentation est pas permis, et comment pouvons-nous l' exploiter? Nous soustrayons q enfoncé dans la pile sur elle sur la longueur des vers de terre après la coupe, nous pouvons utiliser le tas à la main et l' entrée rapide et sortie pour rendre le programme plus rapide. Lorsque vous utilisez modèle STL T priority tombera à un moment donné, je suis ici et entrée-jeu à la main et la pile de sortie pointage optimisé de 85 points, la complexité temporelle de l'algorithme est sur O ((n + m) log (n + m)) code est le suivant:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
const int N = 1e5 + 5, M = 7e6 + 5;
int n, m, q, u, v, t, Add;
double p;
struct BigRt
{
int g[N + M], l;
inline void Pop()
{
g[1] = g[l--];
int now = 1, nxt = 2, res = g[1];
while (nxt <= l)
{
if (nxt < l && g[nxt | 1] > g[nxt])
nxt |= 1;
if (res < g[nxt])
g[now] = g[nxt], nxt = (now = nxt) << 1;
else break;
}
g[now] = res;
}
inline void Push(const int &res)
{
g[++l] = res;
int now = l, nxt = l >> 1;
while (nxt)
{
if (res > g[nxt])
g[now] = g[nxt], nxt = (now = nxt) >> 1;
else break;
}
g[now] = res;
}
}Q;
inline int get()
{
char ch; int res = 0; bool f = true;
while (((ch = getchar()) < '0' || ch > '9') && ch != '-');
if (ch == '-') f = false;
else res = ch - '0';
while ((ch = getchar()) >= '0' && ch <= '9')
res = (res << 3) + (res << 1) + ch - '0';
return f? res : -res;
}
inline void put(int x)
{
if (x < 0)
x = -x, putchar('-');
if (x > 9) put(x / 10);
putchar(x % 10 + 48);
}
inline bool cmp(const int &x, const int &y) {return x > y;}
int main()
{
n = get(); m = get(); q = get();
u = get(); v = get(); t = get();
p = (double)u / v; Q.l = 0;
for (int i = 1; i <= n; ++i) Q.Push(get());
for (int i = 1; i <= m; ++i)
{
int x = Q.g[1] + Add; Q.Pop();
if (i % t == 0) put(x), putchar(' ');
int l = (int)(p * x), r = x - l;
Q.Push(l - Add - q); Q.Push(r - Add - q);
Add += q;
(i % t == 0) put(Q.g[1] + Add), putchar(' ');
Q.Pop();
}
}
[100]
Maintenant , nous pouvons l' améliorer, donc nous
pensions que, si nous avions deux vers de terre vers de terre à l1, après la division ont été mis à l2, l3, alors il doit être l2 <= l1, l3 <= l1 est clairement établie alors on peut définir trois files d' attente communes représentent des vers de terre non coupée q1, q2 coupant à travers la moitié gauche, sont découpées à travers la moitié de Q3, Q1 lors de la saisie des données, l'ordre décroissant, chacune à découper lors du retrait du premier escadron de trois files d' attente après la coupe maximale , comme les segments de découpe sont pressées dans la q2 droite et à gauche, q3 de la queue et d' autres moyens ayant le même traitement de segment de mémoire, la complexité temporelle de l' algorithme est en O (n + m ), il est clair beaucoup plus rapide, avec un temps total de 1528ms
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
const int Maxn = 2147483647;
const int N = 1e5 + 5, M = 7e6 + 5;
int n, m, q, u, v, t, Add;
int Q[3][M], qt[3], qw[3];
inline int get()
{
char ch; int res;
while ((ch = getchar()) < '0' || ch > '9');
res = ch - '0';
while ((ch = getchar()) >= '0' && ch <= '9')
res = (res << 3) + (res << 1) + ch - '0';
return res;
}
inline void put(int x)
{
if (x > 9) put(x / 10);
putchar(x % 10 + 48);
}
inline bool cmp(const int &x, const int &y) {return x > y;}
inline int GetMax()
{
int res = -Maxn, k;
for (int i = 0; i < 3; ++i)
if (qt[i] < qw[i] && res < Q[i][qt[i] + 1])
res = Q[i][qt[i] + 1], k = i;
qt[k]++; return res;
}
int main()
{
n = get(); m = get(); q = get();
u = get(); v = get(); t = get();
for (int i = 1; i <= n; ++i) Q[0][++qw[0]] = get();
sort(Q[0] + 1, Q[0] + qw[0] + 1, cmp);
for (int i = 1; i <= m; ++i)
{
int x = GetMax() + Add;
if (i % t == 0) put(x), putchar(i + t > m ? '\n' : ' ');
int l = (ll)x * u / v, r = x - l;
Q[1][++qw[1]] = l - Add - q;
Q[2][++qw[2]] = r - Add - q; Add += q;
}
if (t > m) putchar('\n');
int tmp = n + m;
for (int i = 1; i <= tmp; ++i)
{
int x = GetMax() + Add;
if (i % t == 0) {put(x); if (i + t <= tmp) putchar(' ');}
}
return 0;
}