线段树题目,很简单。需要预处理一下,树的节点中存储的元素为区间的两个端点,然后该段中最大的值,还有延迟标记。预处理的时候先求出所有长度为k的序列的长度,然后建树。具体的程序如下:开始的时候忽略了测试例子数,所以一直runtime error。
/*
ID : csuchenan
PEOG: D Garden
LANG: C++
*/
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define MAXN 201000
using namespace std ;
struct Node{
int l ;
int r ;
int flag ;
int nmax ;
}node[4*MAXN] ;
int nsum[MAXN] ;
int nval[MAXN] ;
int n ;
int m ;
int k ;
bool init() ;
void work() ;
void pushdown(int root) ;
void pushup(int root) ;
void solve(int x , int y) ;
void build(int l , int r , int c) ;
void update(int l , int r , int val , int c) ;
long long query(int l , int r , int c);
int main(){
int t ;
scanf("%d" , &t) ;
//freopen("out.txt" , "w" , stdout) ;
while(t--){
init() ;
work() ;
}
return 0 ;
}
bool init(){
if(scanf("%d %d %d" , &n , &m , &k)!=3){
return 0 ;
}
memset(nsum , 0 , sizeof(nsum)) ;
int i ;
int j ;
i = 1 ;
while(i <= n){
scanf("%d" , &nval[i]);
i++ ;
}
for(i = 1 ; i <= k ; i ++)
nsum[1] += nval[i] ;
j = 2 ;
for(i = k + 1 ; i <= n ; i ++){
nsum[j] = nsum[j-1] + nval[i] - nval[i-k] ;
j ++ ;
}
build(1 , n - k + 1 , 1) ;
return 1 ;
}
void work(){
int x ;
int y ;
int p ;
int l ;
int r ;
while(m--){
scanf("%d %d %d" , &p , &x , &y) ;
if(p==0){
solve(x , y - nval[x]) ;
nval[x] = y ;
}
else if(p==1){
solve(x , nval[y] - nval[x]) ;
solve(y , nval[x] - nval[y]) ;
int temp = nval[x] ;
nval[x] = nval[y] ;
nval[y] = temp ;
}
else{
l = x ;
r = y - k + 1 ;
printf("%d\n", query(l , r , 1)) ;
}
}
}
void solve(int x , int y){
int l ;
int r ;
l = x - k + 1 ;
if(l < 1)
l = 1 ;
r = x ;
if(x + k - 1 > n)
r = n - k + 1 ;
update(l , r , y , 1) ;
}
void build(int l , int r , int c){
node[c].l = l ;
node[c].r = r ;
node[c].flag = 0 ;
if(l == r){
node[c].nmax = nsum[l] ;
return ;
}
int mid = (l + r)/2 ;
build(l , mid , c * 2) ;
build(mid + 1 , r , c * 2 + 1) ;
pushup(c) ;
}
void pushup(int root){
node[root].nmax = max(node[root * 2].nmax , node[root * 2 + 1].nmax) ;
}
void pushdown(int root){
if(node[root].flag==0)
return ;
node[root*2].flag += node[root].flag ;
node[root*2+1].flag += node[root].flag ;
node[root*2].nmax += node[root].flag ;
node[root*2+1].nmax += node[root].flag ;
node[root].flag = 0 ;
}
void update(int l , int r , int val , int c){
pushdown(c) ;
if(l == node[c].l && node[c].r == r){
node[c].flag += val ;
node[c].nmax += val ;
return ;
}
//pushdown(c) ;
int mid = (node[c].l + node[c].r)/2 ;
if(r <= mid){
update(l , r , val , c*2) ;
}
else if(mid < l){
update(l , r , val , c*2+1) ;
}
else{
update(l , mid , val , c*2) ;
update(mid + 1 , r , val , c*2+1) ;
}
pushup(c) ;
}
long long query(int l , int r , int c){
pushdown(c) ;
if(l == node[c].l && r == node[c].r){
return node[c].nmax ;
}
int mid = (node[c].l + node[c].r)/2 ;
if(r <= mid){
return query(l , r , c * 2) ;
}
if(l > mid){
return query(l , r , c * 2 + 1) ;
}
return max(query(l , mid , c * 2 ) , query(mid + 1 , r , c * 2 + 1)) ;
}