GSS

  • GSS1

随便猫树或者线段树,就可以过了

猫树不说,线段树可以维护左边最大,右边最大,区间最大,区间值然后就做出来了。

//Isaunoya
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#include<bits/stdc++.h>
using namespace std ;
inline int read() { register int x = 0 ; register int f = 1 ; register char c = getchar() ;
for( ; ! isdigit(c) ; c = getchar()) if(c == '-') f = -1 ;
for( ; isdigit(c) ; c = getchar()) x = (x << 1) + (x << 3) + (c & 15) ;
return x * f ;
} int st[105] ;
template < typename T > inline void write(T x , char c = '\n') { int tp = 0 ;
if(x == 0) return (void) puts("0") ;
if(x < 0) putchar('-') , x = -x ;
for( ; x ; x /= 10) st[++ tp] = x % 10 ;
for( ; tp ; tp --) putchar(st[tp] + '0') ;
putchar(c) ;
}
//#define Online_Judge
const int N = 50000 + 10 ;
int n , m ;
int a[N] ;
int p[21][N << 2] , s[21][N << 2] ;
int Log[N << 2] , d[N << 3] ;
inline void build(int l , int r , int rt , int dep) {
if(l == r) {
d[l] = rt ;
return ;
}
int mid = l + r >> 1 ;
int sum = 0 , pre = 0 ;
p[dep][mid] = s[dep][mid] = sum = pre = a[mid] ;
if(sum < 0) sum = 0 ;
for(register int i = mid - 1 ; i >= l ; i --) {
pre += a[i] ;
sum += a[i] ;
p[dep][i] = max(p[dep][i + 1] , sum) ;
s[dep][i] = max(s[dep][i + 1] , pre) ;
if(sum < 0) sum = 0 ;
}
p[dep][mid + 1] = s[dep][mid + 1] = sum = pre = a[mid + 1] ;
if(sum < 0) sum = 0 ;
for(register int i = mid + 2 ; i <= r ; i ++) {
pre += a[i] ;
sum += a[i] ;
p[dep][i] = max(p[dep][i - 1] , sum) ;
s[dep][i] = max(s[dep][i - 1] , pre) ;
if(sum < 0) sum = 0 ;
}
build(l , mid , rt << 1 , dep + 1) ;
build(mid + 1 , r , rt << 1 | 1 , dep + 1) ;
}
inline int Query(int l , int r) {
if(l == r) return a[l] ;
int st = Log[d[l]] - Log[d[l] ^ d[r]] ;
return max(max(p[st][l] , p[st][r]) , s[st][l] + s[st][r]) ;
} signed main() {
#ifdef Online_Judge
freopen("testdata.in" , "r" , stdin) ;
freopen("testdata2.out" , "w" , stdout) ;
#endif
n = read() ;
for(register int i = 1 ; i <= n ; i ++) a[i] = read() ;
int len = 2 ;
for( ; len < n ; len <<= 1) ;
for(register int i = 2 ; i <= len << 1 ; i ++) Log[i] = Log[i >> 1] + 1 ;
build(1 , len , 1 , 1) ;
m = read() ;
for(register int i = 1 ; i <= m ; i ++) {
int l = read() , r = read() ;
write(Query(l , r)) ;
}
return 0 ;
}
  • GSS2

离线,用树状数组的方法加入数字,只不过是要维护历史最值,这题又没了。

#include <bits/stdc++.h>
#define rep(i , x , y) for(register int i = (x) , _## i = (y + 1) ; i < _## i ; i ++)
#define Rep(i , x , y) for(register int i = (x) , _## i = (y - 1) ; i > _## i ; i --)
using namespace std ;
using ll = long long ;
using pii = pair < int , int > ;
const static int _ = 1 << 20 ;
char fin[_] , * p1 = fin , * p2 = fin ;
inline char gc() { return (p1 == p2) && (p2 = (p1 = fin) + fread(fin , 1 , _ , stdin) , p1 == p2) ? EOF : * p1 ++ ; }
inline int read() {
bool sign = 1 ; char c = 0 ; while(c < 48) ((c = gc()) == 45) && (sign = 0) ;
int x = (c & 15) ; while((c = gc()) > 47) x = (x << 1) + (x << 3) + (c & 15) ;
return sign ? x : -x ;
}
template < class T > void print(T x , char c = '\n') {
(x == 0) && (putchar(48)) , (x < 0) && (putchar(45) , x = -x) ;
static char _st[100] ; int _stp = 0 ;
while(x) _st[++ _stp] = x % 10 ^ 48 , x /= 10 ;
while(_stp) putchar(_st[_stp --]) ; putchar(c) ;
}
template < class T > void cmax(T & x , T y) { (x < y) && (x = y) ; }
template < class T > void cmin(T & x , T y) { (x > y) && (x = y) ; } int n , q ;
const int N = 1e5 + 10 ;
int a[N] ;
vector < pii > vr[N] ;
ll ans[N] ;
int mp[N << 1] ;
struct Node {
ll mx , hsmx , tag , hstag ;
Node operator + (const Node & other) const {
Node c ;
c.mx = max(mx , other.mx) ; c.hsmx = max(hsmx , other.hsmx) ;
c.tag = c.hstag = 0 ; return c ;
}
} s[N << 2] ;
inline void pushdown(int rt) {
s[rt << 1].hsmx = max(s[rt << 1].hsmx , s[rt << 1].mx + s[rt].hstag) ;
s[rt << 1].hstag = max(s[rt << 1].hstag , s[rt << 1].tag + s[rt].hstag) ;
s[rt << 1].mx += s[rt].tag ; s[rt << 1].tag += s[rt].tag ;
s[rt << 1 | 1].hsmx = max(s[rt << 1 | 1].hsmx , s[rt << 1 | 1].mx + s[rt].hstag) ;
s[rt << 1 | 1].hstag = max(s[rt << 1 | 1].hstag , s[rt << 1 | 1].tag + s[rt].hstag) ;
s[rt << 1 | 1].mx += s[rt].tag ; s[rt << 1 | 1].tag += s[rt].tag ;
s[rt].tag = s[rt].hstag = 0 ;
}
void modify(int a , int b , int l , int r , int rt , int val) {
if(a <= l && r <= b) {
s[rt].mx += val ; s[rt].tag += val ;
cmax(s[rt].hsmx , s[rt].mx) ; cmax(s[rt].hstag , s[rt].tag) ;
return ;
}
int mid = l + r >> 1 ; pushdown(rt) ;
if(a <= mid) modify(a , b , l , mid , rt << 1 , val) ;
if(b > mid) modify(a , b , mid + 1 , r , rt << 1 | 1 , val) ;
s[rt] = s[rt << 1] + s[rt << 1 | 1] ;
}
Node query(int a , int b , int l , int r , int rt) {
if(a <= l && r <= b) return s[rt] ; pushdown(rt) ;
int mid = l + r >> 1 ;
if(b <= mid) return query(a , b , l , mid , rt << 1) ;
if(a > mid) return query(a , b , mid + 1 , r , rt << 1 | 1) ;
return query(a , b , l , mid , rt << 1) + query(a , b , mid + 1 , r , rt << 1 | 1) ;
}
signed main() {
#ifdef _WIN64
freopen("testdata.in" , "r" , stdin) ;
#endif
n = read() ;
rep(i , 1 , n) a[i] = read() ;
q = read() ;
rep(i , 1 , q) {
int l = read() , r = read() ;
vr[r].push_back({ l , i }) ;
}
rep(i , 1 , n) {
modify(mp[a[i] + N] + 1 , i , 1 , n , 1 , a[i]) ;
mp[a[i] + N] = i ;
for(auto x : vr[i]) ans[x.second] = query(x.first , i , 1 , n , 1).hsmx ;
}
rep(i , 1 , q) print(ans[i]) ;
return 0 ;
}
  • GSS3

和 GSS1 一个样子,随便写,随便过了…

// Isaunoya
#include<bits/stdc++.h>
using namespace std ;
#define int long long
#define fi first
#define se second
#define pb push_back
inline int read() {
register int x = 0 , f = 1 ;
register char c = getchar() ;
for( ; ! isdigit(c) ; c = getchar()) if(c == '-') f = -1 ;
for( ; isdigit(c) ; c = getchar()) x = (x << 1) + (x << 3) + (c & 15) ;
return x * f ;
}
template < typename T > inline bool cmax(T & x , T y) {
return x < y ? (x = y) , 1 : 0 ;
}
template < typename T > inline bool cmin(T & x , T y) {
return x > y ? (x = y) , 1 : 0 ;
}
inline int QP(int x , int y , int Mod){ int ans = 1 ;
for( ; y ; y >>= 1 , x = (x * x) % Mod)
if(y & 1) ans = (ans * x) % Mod ;
return ans ;
} int n , q ;
struct node {
int l , r , sum , res ;
} ;
const int N = 5e4 + 5 ;
int a[N] ;
node s[N << 2] ; inline void pushup(int rt) {
node l = s[rt << 1] , r = s[rt << 1 | 1] ;
s[rt].sum = l.sum + r.sum ;
s[rt].l = max(l.l , l.sum + r.l) ;
s[rt].r = max(r.r , r.sum + l.r) ;
s[rt].res = max(l.r + r.l , max(l.res , r.res)) ;
}
inline void build(int l , int r , int rt) {
if(l == r) { s[rt] = {a[l] , a[l] , a[l] , a[l]} ; return ; }
int mid = l + r >> 1 ;
build(l , mid , rt << 1) ;
build(mid + 1 , r , rt << 1 | 1) ;
pushup(rt) ;
}
inline void modify(int x , int l , int r , int rt , int val) {
if(l == r) {
s[rt] = {val , val , val , val} ;
return ;
}
int mid = l + r >> 1 ;
if(x <= mid) modify(x , l , mid , rt << 1 , val) ;
else modify(x , mid + 1 , r , rt << 1 | 1 , val) ;
pushup(rt) ;
} inline node Merge(node x , node y) {
if(x.l == -19260817 && y.l == -19260817) return {-19260817 , -19260817 , -19260817 , -19260817} ;
if(x.l == -19260817) return y ;
if(y.l == -19260817) return x ;
node res ;
res.sum = x.sum + y.sum ;
res.l = max(x.l , x.sum + y.l) ;
res.r = max(y.r , y.sum + x.r) ;
res.res = max(x.r + y.l , max(x.res , y.res)) ;
return res ;
}
inline node query(int a , int b , int l , int r , int rt) {
if(a <= l && r <= b) return s[rt] ;
int mid = l + r >> 1 ;
node res1 , res2 ;
res1 = {-19260817 , -19260817 , -19260817 , -19260817} ;
res2 = {-19260817 , -19260817 , -19260817 , -19260817} ;
if(a <= mid) res1 = query(a , b , l , mid , rt << 1) ;
if(b > mid) res2 = query(a , b , mid + 1 , r , rt << 1 | 1) ;
return Merge(res1 , res2) ;
}
signed main() {
n = read() ;
for(register int i = 1 ; i <= n ; i ++) a[i] = read() ;
build(1 , n , 1) ;
q = read() ;
while(q --) {
int opt = read() ;
if(opt == 1) {
int x = read() , y = read() ;
printf("%lld\n" , query(x , y , 1 , n , 1).res) ;
}
else {
int x = read() , y = read() ;
modify(x , 1 , n , 1 , y) ;
}
}
return 0 ;
}
  • GSS4

确实水,像是一道分块蓝题…但是线段树也可以做,维护一个区间最值…常用套路?

然后显然是可以做的,这题没了。

#include<bits/stdc++.h>
using namespace std ;
int n , m ;
const static int N = 1e5 + 10 ;
long long a[N] ;
template < typename T > class SegMentTree {
public :
T mx[N << 2] , sum[N << 2] ;
inline T max(T x , T y) {
return x > y ? x : y ;
}
inline void Push_Up(int rt) {
mx[rt] = max(mx[rt << 1] , mx[rt << 1 | 1]) ;
sum[rt] = sum[rt << 1] + sum[rt << 1 | 1] ;
}
inline void build(int l , int r , int rt) {
if(l == r) {
mx[rt] = sum[rt] = a[l] ;
return ;
}
int mid = l + r >> 1 ;
build(l , mid , rt << 1) ;
build(mid + 1 , r , rt << 1 | 1) ;
Push_Up(rt) ;
}
inline void Change(int a , int b , int l , int r , int rt) {
if(mx[rt] == 1) return ;
if(l == r) {
mx[rt] = sum[rt] = sqrt(sum[rt]) ;
return ;
}
int mid = l + r >> 1 ;
if(a <= mid) Change(a , b , l , mid , rt << 1) ;
if(b > mid) Change(a , b , mid + 1 , r , rt << 1 | 1) ;
Push_Up(rt) ;
}
inline T Query(int a , int b , int l , int r , int rt) {
if(a <= l && r <= b) return sum[rt] ;
int mid = l + r >> 1 ;
T ans = 0 ;
if(a <= mid) ans += Query(a , b , l , mid , rt << 1) ;
if(b > mid) ans += Query(a , b , mid + 1 , r , rt << 1 | 1) ;
return ans ;
}
} ;
SegMentTree < long long > T ;
signed main() {
int cnt = 0 ;
while(scanf("%d" , & n) != EOF) {
printf("Case #%d:\n", ++ cnt) ;
for(register int i = 1 ; i <= n ; i ++) scanf("%lld" , & a[i]) ;
T.build(1 , n , 1) ;
scanf("%d" , & m) ;
for( ; m -- ; ) {
int opt , l , r ;
scanf("%d %d %d" , & opt , & l , & r) ;
if(l > r) l ^= r ^= l ^= r ;
if(opt == 0) T.Change(l , r , 1 , n , 1) ;
if(opt == 1) printf("%lld\n" , T.Query(l , r , 1 , n , 1)) ;
}
puts("") ;
}
return 0 ;
}
  • GSS5

猫树,不想说,就是板子

线段树就分类讨论一下情况,这题没了

// Isaunoya
#include<bits/stdc++.h>
using namespace std ;
using LL = long long ;
using uint = unsigned int ;
#define int long long
#define fir first
#define sec second
#define pb push_back
#define mp(x , y) make_pair(x , y)
template < typename T > inline void read(T & x) { x = 0 ; int f = 1 ; register char c = getchar() ;
for( ; ! isdigit(c) ; c = getchar()) if(c == '-') f = -1 ;
for( ; isdigit(c) ; c = getchar()) x = (x << 1) + (x << 3) + (c & 15) ;
x *= f ;
}
template < typename T > inline void print(T x) {
if(! x) { putchar('0') ; return ; }
static int st[105] ;
if(x < 0) putchar('-') , x = -x ;
int tp = 0 ;
while(x) st[++ tp] = x % 10 , x /= 10 ;
while(tp) putchar(st[tp --] + '0') ;
}
template < typename T > inline void print(T x , char c) { print(x) ; putchar(c) ; }
template < typename T , typename ...Args > inline void read(T & x , Args & ...args) { read(x) ; read(args...) ; }
template < typename T > inline void sort( vector < T > & v) { sort(v.begin() , v.end()) ; return ; }
template < typename T > inline void unique( vector < T > & v) { sort(v) ; v.erase(unique(v.begin() , v.end()) , v.end()) ; }
template < typename T > inline void cmax(T & x , T y) { if(x < y) x = y ; return ; }
template < typename T > inline void cmin(T & x , T y) { if(x > y) x = y ; return ; }
const int Mod = LLONG_MAX ;
inline int QP(int x , int y) { int ans = 1 ;
for( ; y ; y >>= 1 , x = (x * x) % Mod)
if(y & 1) ans = (ans * x) % Mod ;
return ans ;
}
template < typename T > inline T gcd(T x , T y) { if(y == 0) return x ; return gcd(y , x % y) ; }
template < typename T > inline T lcm(T x , T y) { return x * y / gcd(x , y) ; }
template < typename T > inline void mul(T & x , T y) { x = 1LL * x * y ; if(x >= Mod) x %= Mod ; }
template < typename T > inline void add(T & x , T y) { if((x += y) >= Mod) x -= Mod ; }
template < typename T > inline void sub(T & x , T y) { if((x -= y) < 0) x += Mod ; } int n , q ;
const int N = 2e5 + 10 ;
int a[N] , pos[N] , p[16][N] , f[16][N] , sum[16][N] , e_sum[16][N] , lg[N << 2] ; #define rep(i , j , n) for(register int i = j ; i <= n ; i ++)
#define Rep(i , j , n) for(register int i = j ; i >= n ; i --)
inline void build(int l , int r , int k , int d) {
if(l == r) { pos[l] = k ; return ; }
int sum1 = 0 , sum2 = 0 , mid = l + r >> 1 ;
p[d][mid] = f[d][mid] = sum[d][mid] = e_sum[d][mid] = sum1 = sum2 = a[mid] ;
cmax(sum2 , 0LL) ;
Rep(i , mid - 1 , l) { sum1 += a[i] , sum2 += a[i] ;
p[d][i] = max(p[d][i + 1] , sum1) ;
f[d][i] = max(f[d][i + 1] , sum2) ;
sum[d][i] = sum1 ;
e_sum[d][i] = sum2 ;
cmax(sum2 , 0LL) ;
}
p[d][mid + 1] = f[d][mid + 1] = sum[d][mid + 1] = e_sum[d][mid + 1] = sum1 = sum2 = a[mid + 1] ;
cmax(sum2 , 0LL) ;
rep(i , mid + 2 , r) { sum1 += a[i] , sum2 += a[i] ;
p[d][i] = max(p[d][i - 1] , sum1) ;
f[d][i] = max(f[d][i - 1] , sum2) ;
sum[d][i] = sum1 ;
e_sum[d][i] = sum2 ;
cmax(sum2 , 0LL) ;
}
build(l , mid , k << 1 , d + 1) ;
build(mid + 1 , r , k << 1 | 1 , d + 1) ;
}
inline int s_query(int l , int r) {
if(l > r) return 0 ;
if(l == r) return a[l] ;
int d = lg[pos[l]] - lg[pos[l] ^ pos[r]] ;
return sum[d][l] + sum[d][r] ;
}
inline int pre_query(int l , int r) {
if(l > r) return 0 ;
if(l == r) return a[l] ;
int d = lg[pos[l]] - lg[pos[l] ^ pos[r]] ;
return max(e_sum[d][l] , sum[d][l] + p[d][r]) ;
}
inline int suc_query(int l , int r) {
if(l > r) return 0 ;
if(l == r) return a[l] ;
int d = lg[pos[l]] - lg[pos[l] ^ pos[r]] ;
return max(e_sum[d][r] , sum[d][r] + p[d][l]) ;
}
inline int m_query(int l , int r) {
if(l > r) return 0 ;
if(l == r) return a[l] ;
int d = lg[pos[l]] - lg[pos[l] ^ pos[r]] ;
return max(max(f[d][l] , f[d][r]) , p[d][l] + p[d][r]) ;
}
inline int query(int l, int r , int l2 , int r2) {
int ans = 0 ;
if(r < l2) return s_query(r + 1 , l2 - 1) + suc_query(l , r) + pre_query(l2 , r2) ;
ans = m_query(l2 , r) ;
if(l < l2) cmax(ans , suc_query(l , l2) + pre_query(l2 , r2) - a[l2]) ;
if(r2 > r) cmax(ans , suc_query(l , r) + pre_query(r , r2) - a[r]) ;
return ans ;
}
signed solve() {
read(n) ;
memset(a , 0 , sizeof(a)) ;
for(register int i = 1 ; i <= n ; i ++) read(a[i]) ;
read(q) ;
int len = 2 ; while(len < n) len <<= 1 ;
build(1 , len , 1 , 1) ;
while(q -- ) {
int l , r , l2 , r2 ; read(l , r , l2 , r2) ;
print(query(l , r , l2 , r2) , '\n') ;
}
return 0 ;
} signed main() {
for(register int i = 2 ; i <= N ; i ++) lg[i] = lg[i >> 1] + 1 ;
int t ; read(t) ;
while(t --) {
solve() ;
}
}
  • GSS6

没有NOI2005的那题难,随便写fhq就能过。

不想写了…代码咕着

事实证明这玩意改改就能过

#include<bits/stdc++.h>
using namespace std ;
const static int _ = 1 << 20 ;
char fin[_] , * p1 = fin , * p2 = fin ;
inline char gc() { return (p1 == p2) && (p2 = (p1 = fin) + fread(fin , 1 , _ , stdin) , p1 == p2) ? EOF : * p1 ++ ; }
inline int read() {
bool sign = 1 ; char c = 0 ; while(c < 48) ((c = gc()) == 45) && (sign = 0) ;
int x = (c & 15) ; while((c = gc()) > 47) x = (x << 1) + (x << 3) + (c & 15) ;
return sign ? x : -x ;
}
template < class T > void print(T x , char c = '\n') {
(x == 0) && (putchar(48)) , (x < 0) && (putchar(45) , x = -x) ;
static char _st[100] ; int _stp = 0 ;
while(x) _st[++ _stp] = x % 10 ^ 48 , x /= 10 ;
while(_stp) putchar(_st[_stp --]) ; putchar(c) ;
}
int n , m , rt , cnt = 0 ;
constexpr int N = 2e5 + 10 ;
int a[N] ;
int rnd[N] , val[N] , sum[N] , sz[N] , ls[N] , rs[N] ;
int lmax[N] , rmax[N] , mx[N] ;
int max(int x , int y) {
return x > y ? x : y ;
}
int min(int x , int y ){
return x < y ? x : y ;
}
void pushup(int o) {
sz[o] = sz[ls[o]] + sz[rs[o]] + 1 ;
sum[o] = sum[ls[o]] + sum[rs[o]] + val[o] ;
lmax[o] = max(lmax[ls[o]] , sum[ls[o]] + max(0 , lmax[rs[o]]) + val[o]) ;
rmax[o] = max(rmax[rs[o]] , sum[rs[o]] + max(0 , rmax[ls[o]]) + val[o]) ;
mx[o] = max(0 , rmax[ls[o]]) + max(0 , lmax[rs[o]]) + val[o] ;
if(ls[o]) mx[o] = max(mx[o] , mx[ls[o]]) ;
if(rs[o]) mx[o] = max(mx[o] , mx[rs[o]]) ;
}
int newnode(int k) {
++ cnt ;
rnd[cnt] = rand() ;
val[cnt] = sum[cnt] = k ;
lmax[cnt] = rmax[cnt] = mx[cnt] = k ;
sz[cnt] = 1 ;
ls[cnt] = rs[cnt] = 0 ;
return cnt ;
}
int merge(int x , int y) {
if(! x || ! y) return x | y ;
if(rnd[x] < rnd[y]) {
rs[x] = merge(rs[x] , y) ;
pushup(x) ;
return x ;
} else {
ls[y] = merge(x , ls[y]) ;
pushup(y) ;
return y ;
}
}
void split(int cur , int k , int & x , int & y) {
if(! cur) {
x = y = 0 ;
return ;
}
if(sz[ls[cur]] < k) {
split(rs[cur] , k - sz[ls[cur]] - 1 , x , y) ;
rs[cur] = 0 ;
pushup(cur) ;
x = merge(cur , x) ;
} else {
split(ls[cur] , k , x , y) ;
ls[cur] = 0 ;
pushup(cur) ;
y = merge(y , cur) ;
}
}
int newrt(int len) {
int _newrt = 0 ;
for(int i = 1 ; i <= len ; i ++) _newrt = merge(_newrt , newnode(read())) ;
return _newrt ;
}
void insert(int pos , int len) {
int x , y ;
split(rt , pos , x , y) ;
rt = merge(merge(x , newrt(len)) , y) ;
}
void remove(int l , int r) {
int x , y , z ;
split(rt , l - 1 , x , z) ;
split(z , r - l + 1 , y , z) ;
rt = merge(x , z) ;
}
int query_max_sum(int l , int r) {
int x , y , z ;
split(rt , l - 1 , x , z) ;
split(z , r - l + 1 , y , z) ;
int res = mx[y] ;
rt = merge(merge(x , y) , z) ;
return res ;
}
int main() {
#ifdef _WIN64
freopen("testdata.in" , "r" , stdin) ;
#endif
srand(19260817) ; n = read() ; rt = newrt(n) ; m = read() ;
while(m --) {
char opt = gc() ; while(opt < 'D' || opt > 'R') opt = gc() ;
if(opt == 'I') {
int pos = read() ; pos -- ;
insert(pos , 1) ;
}
if(opt == 'D') {
int pos = read() ;
remove(pos , pos) ;
}
if(opt == 'R') {
int pos = read() ;
remove(pos , pos) ; pos -- ;
insert(pos , 1) ;
}
if(opt == 'Q') {
int l = read() , r = read() ;
print(query_max_sum(l , r)) ;
}
}
return 0 ;
}
  • GSS7

只需要管一下合并,左链翻转/右链翻转,这题就没了。

虽然说tag初值=0调了好久就是了

#include <bits/stdc++.h>
#define rep(i , x , y) for(register int i = (x) , _## i = (y + 1) ; i < _## i ; i ++)
#define Rep(i , x , y) for(register int i = (x) , _## i = (y - 1) ; i > _## i ; i --)
using namespace std ;
using ll = long long ;
using pii = pair < int , int > ;
const static int _ = 1 << 20 ;
char fin[_] , * p1 = fin , * p2 = fin ;
inline char gc() { return (p1 == p2) && (p2 = (p1 = fin) + fread(fin , 1 , _ , stdin) , p1 == p2) ? EOF : * p1 ++ ; }
inline int read() {
bool sign = 1 ; char c = 0 ; while(c < 48) ((c = gc()) == 45) && (sign = 0) ;
int x = (c & 15) ; while((c = gc()) > 47) x = (x << 1) + (x << 3) + (c & 15) ;
return sign ? x : -x ;
}
template < class T > void print(T x , char c = '\n') {
(x == 0) && (putchar(48)) , (x < 0) && (putchar(45) , x = -x) ;
static char _st[100] ; int _stp = 0 ;
while(x) _st[++ _stp] = x % 10 ^ 48 , x /= 10 ;
while(_stp) putchar(_st[_stp --]) ; putchar(c) ;
}
template < class T > void cmax(T & x , T y) { (x < y) && (x = y) ; }
template < class T > void cmin(T & x , T y) { (x > y) && (x = y) ; }
struct Node {
int mx , lmx , rmx , sum , tag ;
void operator = (int x) { sum = x ; mx = lmx = rmx = max(0 , sum) ; }
} ;
Node Merge(Node x , Node y) {
Node res ;
res.lmx = max(x.lmx , x.sum + y.lmx) ;
res.rmx = max(y.rmx , y.sum + x.rmx) ;
res.sum = x.sum + y.sum ;
res.mx = max(max(x.mx , y.mx) , x.rmx + y.lmx) ;
res.tag = 1e7 ;
return res ;
}
int n , q ;
const int N = 1e5 + 10 ;
const int inf = 1e7 ;
Node s[N << 2] ;
vector < int > G[N] ;
int v[N] , a[N] , fa[N] , id[N] , idx = 0 , d[N] , sz[N] , son[N] , top[N] ;
void dfs(int u) {
sz[u] = 1 ; for(auto v : G[u]) {
if(v == fa[u]) continue ;
fa[v] = u ; d[v] = d[u] + 1 ;
dfs(v) ; sz[u] += sz[v] ;
if(sz[v] > sz[son[u]]) son[u] = v ;
}
}
void dfs(int u , int t) {
top[u] = t ; a[id[u] = ++ idx] = v[u] ;
if(son[u]) dfs(son[u] , t) ;
for(auto v : G[u]) {
if(v == fa[u] || v == son[u]) continue ;
dfs(v , v) ;
}
}
void build(int l , int r , int rt) {
s[rt].tag = inf ;
if(l == r) { s[rt] = a[l] ; return ; }
int mid = l + r >> 1 ;
build(l , mid , rt << 1) ;
build(mid + 1 , r , rt << 1 | 1) ;
s[rt] = Merge(s[rt << 1] , s[rt << 1 | 1]) ;
}
void cover(int rt , int l , int r , int val) {
s[rt] = (r - l + 1) * val ;
s[rt].tag = val ;
}
void pushdown(int rt , int l , int r) {
if(s[rt].tag == inf) return ;
int mid = l + r >> 1 ;
cover(rt << 1 , l , mid , s[rt].tag) ;
cover(rt << 1 | 1 , mid + 1 , r , s[rt].tag) ;
s[rt].tag = inf ;
}
void change(int a , int b , int l , int r , int rt , int val) {
if(a <= l && r <= b) {
cover(rt , l , r , val) ;
return ;
}
pushdown(rt , l , r) ;
int mid = l + r >> 1 ;
if(a <= mid) change(a , b , l , mid , rt << 1 , val) ;
if(b > mid) change(a , b , mid + 1 , r , rt << 1 | 1 , val) ;
s[rt] = Merge(s[rt << 1] , s[rt << 1 | 1]) ;
}
Node query(int a , int b , int l , int r , int rt) {
if(a <= l && r <= b) return s[rt] ;
pushdown(rt , l , r) ;
int mid = l + r >> 1 ;
Node L = { 0 , 0 , 0 , 0 , 0 } , R = { 0 , 0 , 0 , 0 , 0 } ;
if(a <= mid) L = query(a , b , l , mid , rt << 1) ;
if(b > mid) R = query(a , b , mid + 1 , r , rt << 1 | 1) ;
return Merge(L , R) ;
}
void change(int x , int y , int val) {
while(top[x] != top[y]) {
if(d[top[x]] < d[top[y]]) swap(x , y) ;
change(id[top[x]] , id[x] , 1 , n , 1 , val) ;
x = fa[top[x]] ;
}
if(d[x] > d[y]) swap(x , y) ;
change(id[x] , id[y] , 1 , n , 1 , val) ;
}
Node query(int x , int y) {
Node L = { 0 , 0 , 0 , 0 } , R = { 0 , 0 , 0 , 0 } ;
while(top[x] ^ top[y]) {
if(d[top[x]] > d[top[y]]) {
L = Merge(query(id[top[x]] , id[x] , 1 , n , 1) , L) ;
x = fa[top[x]] ;
}
else {
R = Merge(query(id[top[y]] , id[y] , 1 , n , 1) , R) ;
y = fa[top[y]] ;
}
}
if(d[x] > d[y]) {
L = Merge(query(id[y] , id[x] , 1 , n , 1) , L) ;
}
else {
R = Merge(query(id[x] , id[y] , 1 , n , 1) , R) ;
}
swap(L.lmx , L.rmx) ;
return Merge(L , R) ;
} signed main() {
#ifdef _WIN64
freopen("testdata.in" , "r" , stdin) ;
freopen("testdata.out" , "w" , stdout) ;
#endif
n = read() ;
rep(i , 1 , n) v[i] = read() ;
rep(i , 2 , n) {
int u = read() , v = read();
G[u].push_back(v) ;
G[v].push_back(u) ;
}
dfs(1) ;
dfs(1 , 1) ;
build(1 , n , 1) ;
q = read() ;
while(q --) {
int opt = read() ;
if(opt == 1) {
int x = read() , y = read() ;
print(query(x , y).mx) ;
}
else {
int x = read() , y = read() , val = read() ;
change(x , y , val) ;
}
}
return 0 ;
}
  • GSS8

还没写,咕着。

GSS 系列题解的更多相关文章

  1. GSS系列题解——最大子段和系列

    开坑啦! 2019 3/28 以前一直不知道怎么搞最大子段和,如今终于可以学习,其实真的很简单啊. 2019 3/29 树链剖分上最大子段和也OK啦 前置技能:线段树 题目大意:询问区间[l,r]的最 ...

  2. IEEE Bigger系列题解

    Bigger系列题解 Bigger Python 坑点在于要高精度以及表达式求值,用java写可以很容易避免高精度问题 然后这道题就可以AC了 代码 import java.io.*; import ...

  3. SPOJ GSS 系列

    来怒做GSS系列了: GSS1:https://www.luogu.org/problemnew/show/SP1043 这题就是维护一个 sum , mx , lmx , rmx,转移时用结构体就好 ...

  4. spoj GSS系列简要题解

    文章目录 GSS1 GSS2 GSS3 GSS4 GSS5 GSS6 GSS7 GSS8 传送门 这个GSSGSSGSS系列全部是跟子段有关的数据结构菜题. 于是来水一篇博客. GSS1 传送门 题意 ...

  5. QTREE系列题解

    打了快一星期的qtree终于打完了- - (其实还有两题改不出来弃疗了QAQ) orz神AK一星期前就虐完QTREE 避免忘记还是简单写下题解吧0 0 QTREE1 题意: 给出一颗带边权树 一个操作 ...

  6. SPOJ GSS系列

    众所周知的仅次于ynoi的毒瘤数据结构系列.(跟Qtree系列并列?) GSS1: 长度为 $n$ 的序列 $a$,$m$ 个询问,每次询问区间 $[l,r]$ 之间的最大子段和. $1\le n,m ...

  7. SPOJ GSS系列(数据结构维护技巧入门)

    题目链接 GSS $GSS1$ 对于每个询问$l$, $r$,查询$a_{l}$, $a_{l+1}$, $a_{l+2}$, ..., $a_{r}$这个序列的最大字段和. 建立线段树,每个节点维护 ...

  8. 【题解】NOI 系列题解总集

    每次做一道 NOI 系列的估计都很激动吧,对于我这种萌新来说( P1731 [NOI1999]生日蛋糕 练习剪枝技巧,关于剪枝,欢迎看我的垃圾无意义笔记 这道题是有一定难度的,需要运用各种高科技剪枝( ...

  9. 激!GSS系列

    #include <cstdio> ; ; inline int max(int, int); inline int getint(); inline void putint(int); ...

随机推荐

  1. 适合产品经理的十本书 From 俞军

    (转自俞军,如有侵权,请评论区留言,我会尽快删除:) 适合产品经理的十本书 俞军 入门三本书:社会心理学 阿伦森 插图第七版:特别好,适合成为“产品经理的第一本书”第一本经济学:经济学帮助人们洞察世事 ...

  2. 面试题|手写JSON解析器

    这周的 Cassidoo 的每周简讯有这么一个面试题:: 写一个函数,这个函数接收一个正确的 JSON 字符串并将其转化为一个对象(或字典,映射等,这取决于你选择的语言).示例输入: fakePars ...

  3. bash通配符 shell正则表达式

    在linux中 通配符是系统命令使用,一般用来匹配文件名或者什么的用在系统命令中. 通配符是系统级别的,通配符多用在文件名上,比如查找find,ls,cp,rm 正则表达式是操作字符串,以行尾单位来匹 ...

  4. 还是端口回流问题 TCP协议解析

    还是上一篇的问题 在一内部局域网中, client  内网地址为 10.0.0.2     web  服务器内网地址为 10.0.0.1    外网地址为  211.6.15.1    域名为  xx ...

  5. Eclipse 无法引用到Maven 解决方法

    问题描述:打开Eclipse进入java EE视图下,发现原有的Maven Dependencies目录不存在,显示的是org.maven.ide.eclipse.MAVEN2_CLASSPATH_C ...

  6. [MacOS]MacOS字体文件位置

    $ cd /System/Library/Fonts $ ls Apple Braille Outline 6 Dot.ttf Noteworthy.ttc SFCompactText-Regular ...

  7. mac下搭建http服务器(apache+php),使用homebrew升级php

    新版mac依旧预装了 Apache ,但是已经不能在 「系统偏好设置」中的「Web 共享」来开启了,需要手动通过命令行开启. 启动Apache 启动:sudo apachectl start 停止:s ...

  8. Arm开发板+Qt学习之路-析构函数和对话框一起时

    先记录一下代码 一:先将指针释放掉,在显示对话框 void MainWindow::canResponseError(SendCanMsgThread *sendCanMsgThread ){ std ...

  9. v-charts x轴字体斜显示

    如下图,因为X轴内容太多,放不下,插件默认间隔显示需求:X轴内容要全部显示出来(只有斜显示或固定宽多余的用省略代替,本来需要就是想显示全部内容,所以只能取斜显示的方案) 先看看v-charts的文档: ...

  10. jquery带下拉列表的购物车组件封装

    按照国际惯例先放效果图 安静的时候它长这样 等待加载时它长这样(功能是设置的按需加载,网速慢或者加载数据大时会出现) 加载之后购物车没有商品时这样 有商品长这样 接下来放代码: cart.html & ...