A - 一棵简单的线段树
Time Limit: 2000 MS Memory Limit: 256 MB
人生已如此艰难,让我们活得轻松一点.
给你一个数组 A[1..n]A[1..n],初始时每个元素都为零.
我会请你帮我对数组完成一些操作.
第一种可能,我会给你两个数 pp 和 xx(1≤p≤n1≤p≤n), 请你帮我把数组的第 pp 个元素替换为 xx, 即 A[p]←xA[p]←x.
第二种可能,我会给你两个数 LL 和 RR(1≤L<R≤n1≤L<R≤n), 请你告诉我 A[L],A[L+1],…,A[R]A[L],A[L+1],…,A[R] 这几个数中去掉一个最大值和一个最小值后剩下的数的和是多少.
好了,现在锅都丢给你了,我可以活得轻松一点了.
Input
输入第一行为一个整数 n (2≤n≤106)n (2≤n≤106),表示数组的大小.
第二行有一个整数 m (1≤m≤106)m (1≤m≤106),表示我需要你帮我完成的任务的个数.
第 33 到 m+2m+2 行每行有 3 个整数 o x yo x y. 如果 o=0o=0,代表我需要使 A[x]←yA[x]←y, 此时 1≤x≤n, |y|≤1091≤x≤n, |y|≤109. 如果 o=1o=1,代表我想知道 A[x],A[x+1],…,A[y]A[x],A[x+1],…,A[y] 去掉一个最大值和一个最小值后剩下的数的和为多少, 此时 1≤x<y≤n1≤x<y≤n.
Output
对每个 o=1o=1 的任务, 输出只有一个整数的一行, 该整数表示区间 [x,y][x,y] 中的数 去掉一个最大值和一个最小值后剩下的数的和.
Sample input and output
Sample Input | Sample Output |
---|---|
5 5 0 2 1 0 4 -2 1 1 5 0 1 5 1 1 4 | 0 1 |
对于这题 只要单点更新 三个数组up一下 就可以出答案了
#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
const int MAX_N = 100010;
int MAX[MAX_N<<2],MIN[MAX_N<<2],s[MAX_N<<2];
#define dbg(x) cout<<#x<<" = "<< (x)<< endl
void up(int p){
MAX[p] = max(MAX[p*2],MAX[p*2+1]);
MIN[p] = min(MIN[p*2],MIN[p*2+1]);
s[p] = s[p*2] + s[p*2+1];
}
void build(int p,int l,int r){
if(l==r){
MAX[p] = MIN[p] = s[p] = 0;
return ;
}
int mid =(l+r)>>1;
build (p*2,l,mid);
build(p*2+1,mid+1,r);
up(p);
}
void change(int p,int l,int r,int x,int v){
if(l==r){
MAX[p]=MIN[p]=s[p] = v;
return;
}
int mid =(l+r)>>1;
if(x<=mid) change(p*2,l,mid,x,v);
else change(p*2+1,mid+1,r,x,v);
up(p);
}
void query(int p,int l,int r,int x,int y,int& sum,int& maxx,int& minn){
if(x<=l&&r<=y){
sum += s[p];
maxx=max(MAX[p],maxx);
minn=min(MIN[p],minn);
return;
}
int mid = (l+r)>>1;
if(x<=mid) query(p*2,l,mid,x,y,sum,maxx,minn);
if(y>mid) query(p*2+1,mid+1,r,x,y,sum,maxx,minn);
}
int main(){
int n,m;
scanf("%d%d",&n,&m);
build(1,1,n);
while(m--){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
if(a==0){
change(1,1,n,b,c);
}
else if(a==1){
int sum = 0;
int maxx= -0x3f3f3f3f;
int minn= 0x3f3f3f3f;
query(1,1,n,b,c,sum,maxx,minn);
printf("%d\n",sum-maxx-minn);
}
}
return 0;
}