题面
题解
我们发现经过若干次操作后这些数的相对大小都不会变
排序之后, 就只有一段前缀改为 L , 或一段后缀改为 R 了
考虑这样一个函数
[displaystyle\f(a_1, a_2, a_3) = a_1 * c_i + a_2*a_i + a_3
]
其中 (c_i) 代表 (i) 这个位置现在的数, (a_i) 代表 (i) 这个位置原来的数
那么每次操作都可以看做加这个函数
- 加 (k) , 乘上(f(1, 0, k))
- 减 (k) , 乘上 (f(1, 0, -k))
- 乘 (k) , 乘上 (f(k, 0, 0))
- (@k) , 乘上 (f(1, k, 0))
线段树维护一下就好了
Code
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
const int N = 100005;
typedef long long ll;
using namespace std;
int m, L, R, n, op[N], ans[N], num[N];
char s[104];
struct node
{
int v, id;
bool operator < (const node &p) const
{
return v < p.v;
}
} a[N];
struct Tree { ll mn, mx, p1, p2, p3; } t[N << 2];
template < typename T >
inline T read()
{
T x = 0, w = 1; char c = getchar();
while(c < '0' || c > '9') { if(c == '-') w = -1; c = getchar(); }
while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * w;
}
void pushup(int p) { t[p].mn = t[p << 1].mn, t[p].mx = t[p << 1 | 1].mx; }
void pushtag(int p, int l, int r, ll p1, ll p2, ll p3)
{
t[p].p1 *= p1, t[p].p2 = t[p].p2 * p1 + p2, t[p].p3 = t[p].p3 * p1 + p3;
t[p].mn = t[p].mn * p1 + p2 * a[l].v + p3;
t[p].mx = t[p].mx * p1 + p2 * a[r].v + p3;
}
void pushdown(int p, int l, int r)
{
if(t[p].p1 != 1 || t[p].p2 || t[p].p3)
{
int mid = (l + r) >> 1;
pushtag(p << 1, l, mid, t[p].p1, t[p].p2, t[p].p3);
pushtag(p << 1 | 1, mid + 1, r, t[p].p1, t[p].p2, t[p].p3);
t[p].p1 = 1, t[p].p2 = 0, t[p].p3 = 0;
}
}
void build(int p, int l, int r)
{
t[p].p1 = 1;
if(l == r) return (void) (t[p].mn = t[p].mx = a[l].v);
int mid = (l + r) >> 1;
build(p << 1, l, mid), build(p << 1 | 1, mid + 1, r);
pushup(p);
}
void modifymn(int p, int l, int r)
{
if(l == r) return pushtag(p, l, r, 0, 0, L);
pushdown(p, l, r);
int mid = (l + r) >> 1;
if(t[p << 1 | 1].mn < L)
pushtag(p << 1, l, mid, 0, 0, L), modifymn(p << 1 | 1, mid + 1, r);
else modifymn(p << 1, l, mid);
pushup(p);
}
void modifymx(int p, int l, int r)
{
if(l == r) return pushtag(p, l, r, 0, 0, R);
pushdown(p, l, r);
int mid = (l + r) >> 1;
if(t[p << 1].mx > R)
pushtag(p << 1 | 1, mid + 1, r, 0, 0, R), modifymx(p << 1, l, mid);
else modifymx(p << 1 | 1, mid + 1, r);
pushup(p);
}
void query(int p, int l, int r)
{
if(l == r) return (void) (ans[a[l].id] = t[p].mn);
pushdown(p, l, r);
int mid = (l + r) >> 1;
query(p << 1, l, mid), query(p << 1 | 1, mid + 1, r);
pushup(p);
}
int main()
{
m = read <int> (), L = read <int> (), R = read <int> ();
for(int i = 1; i <= m; i++)
{
scanf("%s", s + 1), num[i] = read <int> ();
if(s[1] == '+') op[i] = 1;
else if(s[1] == '-') op[i] = 1, num[i] = -num[i];
else if(s[1] == '*') op[i] = 2;
else op[i] = 3;
}
n = read <int> ();
for(int i = 1; i <= n; i++) a[i].v = read <int> (), a[i].id = i;
sort(a + 1, a + n + 1), build(1, 1, n);
for(int i = 1; i <= m; i++)
{
if(op[i] == 1) pushtag(1, 1, n, 1, 0, num[i]);
else if(op[i] == 2) pushtag(1, 1, n, num[i], 0, 0);
else if(op[i] == 3) pushtag(1, 1, n, 1, num[i], 0);
if(t[1].mn < L) modifymn(1, 1, n);
if(t[1].mx > R) modifymx(1, 1, n);
}
query(1, 1, n);
for(int i = 1; i <= n; i++) printf("%d
", ans[i]);
return 0;
}