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 系列题解的更多相关文章
- GSS系列题解——最大子段和系列
开坑啦! 2019 3/28 以前一直不知道怎么搞最大子段和,如今终于可以学习,其实真的很简单啊. 2019 3/29 树链剖分上最大子段和也OK啦 前置技能:线段树 题目大意:询问区间[l,r]的最 ...
- IEEE Bigger系列题解
Bigger系列题解 Bigger Python 坑点在于要高精度以及表达式求值,用java写可以很容易避免高精度问题 然后这道题就可以AC了 代码 import java.io.*; import ...
- SPOJ GSS 系列
来怒做GSS系列了: GSS1:https://www.luogu.org/problemnew/show/SP1043 这题就是维护一个 sum , mx , lmx , rmx,转移时用结构体就好 ...
- spoj GSS系列简要题解
文章目录 GSS1 GSS2 GSS3 GSS4 GSS5 GSS6 GSS7 GSS8 传送门 这个GSSGSSGSS系列全部是跟子段有关的数据结构菜题. 于是来水一篇博客. GSS1 传送门 题意 ...
- QTREE系列题解
打了快一星期的qtree终于打完了- - (其实还有两题改不出来弃疗了QAQ) orz神AK一星期前就虐完QTREE 避免忘记还是简单写下题解吧0 0 QTREE1 题意: 给出一颗带边权树 一个操作 ...
- SPOJ GSS系列
众所周知的仅次于ynoi的毒瘤数据结构系列.(跟Qtree系列并列?) GSS1: 长度为 $n$ 的序列 $a$,$m$ 个询问,每次询问区间 $[l,r]$ 之间的最大子段和. $1\le n,m ...
- SPOJ GSS系列(数据结构维护技巧入门)
题目链接 GSS $GSS1$ 对于每个询问$l$, $r$,查询$a_{l}$, $a_{l+1}$, $a_{l+2}$, ..., $a_{r}$这个序列的最大字段和. 建立线段树,每个节点维护 ...
- 【题解】NOI 系列题解总集
每次做一道 NOI 系列的估计都很激动吧,对于我这种萌新来说( P1731 [NOI1999]生日蛋糕 练习剪枝技巧,关于剪枝,欢迎看我的垃圾无意义笔记 这道题是有一定难度的,需要运用各种高科技剪枝( ...
- 激!GSS系列
#include <cstdio> ; ; inline int max(int, int); inline int getint(); inline void putint(int); ...
随机推荐
- Go语言实现:【剑指offer】栈的压入、弹出序列
该题目来源于牛客网<剑指offer>专题. 输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序.假设压入栈的所有数字均不相等.例如序列1,2,3,4,5 ...
- 【基础】CodeBlocks调试器基本使用方法
CodeBlocks是一个开放源码的全功能的跨平台C/C++集成开发环境. 下载地址:http://www.codeblocks.org/downloads/26 其中,Windows环境下可以使用 ...
- idea快速创建一个类 实现一个接口
一 创建一个接口类 二 点击接口名称 按alt + ent 三 选择implement interface 选项 完美!!!!!!!
- Magicodes.IE基础教程之导出Pdf
原文作者:hueifeng 说明 本教程主要说明如何使用Magicodes.IE.Pdf完成Pdf收据导出 要点 导出PDF数据 自定义PDF模板 导出单据 如何批量导出单据 导出特性说明 PdfEx ...
- 试题 基础练习 Huffuman树
试题 基础练习 Huffuman树 试题 基础练习 Huffuman树 翻了翻网上,基本都是暴力排序.我就提供一个最小堆的写法吧! 点击这里,跳转查看最小堆插入删除函数的简单写法 Talk i ...
- MFC/QT 学习笔记(三)——MFC模板创建
新建项目->MFC模板->MFC应用程序->应用程序类型:单个文档:项目样式:MFC 标准->下一步...OK 此时点击运行,可直接弹出窗口. 调整 视图->类视图: · ...
- Charles老版本教程
链接:http://pan.baidu.com/s/1c16PxEo 刮开有奖->密码:dbml 初级篇: 1.1设置代理 1.2参数设置+界面介绍 1.3屏蔽多余数据 1.4请求重发 1.5 ...
- oracle快速创建用户、imp/exp导入导出dmp文件
1.首先我们可以用管理员用户以sysdba的身份登录oracle sqlplus username/password as sysdba 2.然后我就可以来创建用户了. create user use ...
- 回炉重造之重读Windows核心编程-006-线程
线程也是有两部分组成的: 线程的内核对象,操作系统用来管理线程和统计线程信息的地方. 线程堆栈,用于维护现场在执行代码的时候用到的所有函数参数和局部变量. 进程是线程的容器,如果进程中有一个以上的线程 ...
- 硬件知识整理part1--电阻E系列行业规范
仁者,人心也,义者,人路也. --孟子 “ E ”表示“指数间距”(Exponential Spacing) 在上个20世纪的电子管时代,电子元器件厂商为了便于元件规格的管理和选用.大规模生产的电 ...