HDU 5306 Gorgeous Sequence 吉司机线段树
详细的解读看这篇博客,因为他没贴代码,所以我贴一下代码并且说一下题目会卡啥。
这题时间卡的非常死,我在网络上找了四篇博客,只有一篇可以AC,其余三篇全都TLE。
首先就是读入,如果用IO优化的cin是会T掉的,我这边用的是一个快读的板子,有些人scanf和printf也能过,总之不要写IO优化的cin和cout。
另外除了修改操作以外都是不需要pushup的,因为如果我们修改的时候覆盖到一个区间停止了,由于只有区min操作,所以当前区间维护的最大值只有可能比子区间更小,所以只需要把父节点的信息下传,而不需要把子区间的信息重新上传。
mx表示区间最大值,md表示区间严格次大值,mcnt表示区间最大值出现的次数。
另外自己实现一个三元运算符的min和max函数,某人说要比库函数自带的要快。
AC代码如下。
#include <iostream>
#include <algorithm>
#define ll long long
const int N = 1e6 + 10;
#define ls(u) u << 1
#define rs(u) u << 1 | 1
const int INF = 0x3f3f3f3f;
const int LO = 1 << 20 | 1;
char buffer[LO], *S, *TT;
#define getchar() ((S==TT&&(TT=(S=buffer)+fread(buffer,1,LO,stdin),S==TT))?EOF:*S++)
namespace Fio {
inline std::string sread() {
std::string s = "";
char e = getchar();
while (!isdigit(e) && !isalpha(e) && e != '*') e = getchar();
while (isdigit(e) || isalpha(e) || e == '*') s += e, e = getchar();
return s;
}
inline int read() {
int x = 0, y = 1;
char c = getchar();
while (!isdigit(c)) {
if (c == '-') y = -1;
c = getchar();
}
while (isdigit(c)) {
x = (x << 3) + (x << 1) + (c ^ 48);
c = getchar();
}
return x *= y;
}
inline ll readll() {
ll x = 0, y = 1;
char c = getchar();
while (!isdigit(c)) {
if (c == '-') y = -1;
c = getchar();
}
while (isdigit(c)) {
x = (x << 3) + (x << 1) + (c ^ 48);
c = getchar();
}
return x *= y;
}
inline void write(ll x) {
if (x < 0) x = -x, putchar('-');
ll sta[35], top = 0;
do sta[top++] = x % 10, x /= 10;
while (x);
while (top) putchar(sta[--top] + '0');
putchar('\n');
}
inline void write(int x) {
if (x < 0) x = -x, putchar('-');
int sta[35], top = 0;
do sta[top++] = x % 10, x /= 10;
while (x);
while (top) putchar(sta[--top] + '0');
putchar('\n');
}
} using namespace Fio;
int n , m, _;
int ans = INF;
int d1[] = {0, 0, 1, -1};
int d2[] = {1, -1, 0, 0};
int a[N];
int T[N << 2], mx[N << 2], md[N << 2], mcnt[N << 1];
ll sum[N << 2];
int max(int a,int b){return a > b ? a : b;}
int min(int a,int b){return a < b ? a : b;}
inline void pushup(int u){
sum[u] = sum[u << 1] + sum[u << 1 | 1];
if(mx[u << 1] > mx[u << 1 | 1]){
mx[u] = mx[u << 1];
mcnt[u] = mcnt[u << 1];
md[u] = md[u << 1] > mx[u << 1 | 1] ? md[u << 1] : mx[u << 1 | 1];
}else if(mx[u << 1] < mx[u << 1 | 1]){
mx[u] = mx[u << 1 | 1];
mcnt[u] = mcnt[u << 1 | 1];
md[u] = md[u << 1 | 1] > mx[u << 1] ? md[u << 1 | 1] : mx[u << 1];
}else{
mx[u] = mx[u << 1];
mcnt[u] = mcnt[u << 1] + mcnt[u << 1 | 1];
md[u] = md[u << 1] > md[u << 1 | 1] ? md[u << 1] : md[u << 1 | 1];
}
}
inline void build_tree(int u, int l, int r){
if(l == r){
mx[u] = sum[u] = a[l];
md[u] = -INF;
mcnt[u] = 1;
return ;
}
int mid = l + r >> 1;
build_tree(u << 1, l, mid);
build_tree(u << 1 | 1, mid + 1, r);
pushup(u);
}
inline void pushdown(int u){
int ls = u << 1, rs = u << 1 | 1;
if(mx[ls] > mx[u] && md[ls] < mx[u]){
sum[ls] -= 1ll * (mx[ls] - mx[u]) * mcnt[ls];
mx[ls] = mx[u];
}
if(mx[rs] > mx[u] && md[rs] < mx[u]){
sum[rs] -= 1ll * (mx[rs] - mx[u]) * mcnt[rs];
mx[rs] = mx[u];
}
}
inline void modify(int u, int L, int R, int l, int r, int x){
if(mx[u] <= x) return ;
if(L >= l && R <= r && md[u] < x){
sum[u] -= 1ll * (mx[u] - x) * mcnt[u];
mx[u] = x;
return ;
}
pushdown(u);
int mid = L + R >> 1;
if(l <= mid) modify(u << 1, L, mid, l, r, x);
if(r > mid) modify(u << 1 | 1, mid + 1, R, l, r, x);
pushup(u);
}
inline int querymx(int u, int L, int R, int l, int r){
if(L >= l && R <= r) return mx[u];
pushdown(u);
int mid = L + R >> 1;
int res = 0;
if(l <= mid){
int tmp = querymx(u << 1, L, mid, l, r);
res = res > tmp ? res : tmp;
}
if(r > mid){
int tmp = querymx(u << 1 | 1, mid + 1, R, l, r);
res = res > tmp ? res : tmp;
}
return res;
}
inline ll querysum(int u, int L, int R, int l, int r){
if(L >= l && R <= r) return sum[u];
pushdown(u);
int mid = L + R >> 1;
ll res = 0;
if(l <= mid) res += querysum(u << 1, L, mid, l, r);
if(r > mid) res += querysum(u << 1 | 1, mid + 1, R, l, r);
return res;
}
inline void solve(){
n = read(), m = read();
for(int i = 1; i <= n; i ++) a[i] = read();
build_tree(1, 1, n);
while(m --){
int op, l, r, x;
op = read(), l = read(), r = read();
if(op == 0){
x = read();
modify(1, 1, n, l, r, x);
}else if(op == 1){
write(querymx(1, 1, n, l, r));
}else{
write(querysum(1, 1, n, l, r));
}
}
}
int main(){
_ = 1;
_ = read();
while(_ --)
solve();
return 0;
}