题目
A - 一棵简单的线段树
Time Limit: 2000 MS Memory Limit: 256 MB
人生已如此艰难,让我们活得轻松一点.
给你一个数组 A[1..n],初始时每个元素都为零.
我会请你帮我对数组完成一些操作.
第一种可能,我会给你两个数 p 和 x(1≤p≤n), 请你帮我把数组的第 p 个元素替换为 x, 即 A[p]←x.
第二种可能,我会给你两个数 L 和 R(1≤L<R≤n), 请你告诉我 A[L],A[L+1],…,A[R] 这几个数中去掉一个最大值和一个最小值后剩下的数的和是多少.
好了,现在锅都丢给你了,我可以活得轻松一点了.
Input
输入第一行为一个整数 n (2≤n≤106),表示数组的大小.
第二行有一个整数 m (1≤m≤106),表示我需要你帮我完成的任务的个数.
第 3 到 m+2 行每行有 3 个整数 o x y. 如果 o=0,代表我需要使 A[x]←y, 此时 1≤x≤n, |y|≤109. 如果 o=1,代表我想知道 A[x],A[x+1],…,A[y] 去掉一个最大值和一个最小值后剩下的数的和为多少, 此时 1≤x<y≤n.
Output
对每个 o=1 的任务, 输出只有一个整数的一行, 该整数表示区间 [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
UESTC Online Judge
Copyright (C) 2012 - 2018 Ruins He(@ruinshe), Jianjin Fan(@pfctgeorge) and Yun Li(@mzry1992). Project home
Any Problem, Please Report On Issues Page.
这是线段树的模板
线段树无非是将区间对半分开然后处理
每一个节点记录的信息是L,R的信息的总和
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <stack>
#include <set>
#include <map>
#include <queue>
#define scd(a) scanf("%d",&a)
#define scdd(a,b) scanf("%d%d",&a,&b)
#define scddd(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define mset(var,val) memset(var,val,sizeof(var))
#define test(a) cout<<a<<endl
#define test2(a,b) cout<<a<<" "<<b<<endl
#define test3(a,b,c) cout<<a<<" "<<b<<" "<<c<<endl
const int N= 5e6+7;
const int mod =1e9+7;
using namespace std;
typedef long long ll;
ll qR,qL,p,v;
const int MAXN =5E6+7;
const int INF = 1e9+7;
struct segTree
{
ll minv[MAXN];
ll sumv[MAXN];
ll maxv[MAXN];
void update(ll o,ll L,ll R){
ll M = L+(R-L)/2;
if(L==R){
minv[o]=v;
maxv[o]=v;
sumv[o]=v;
}else{
if(p<=M)update(o*2,L,M);else update(o*2+1,M+1,R);
minv[o] = min(minv[o*2],minv[o*2+1]);
maxv[o] = max(maxv[o*2],maxv[o*2+1]);
sumv[o] = sumv[o*2]+sumv[o*2+1];
}
}
ll queryMinv(ll o,ll L,ll R){
ll M = L + (R-L)/2,ans = INF;
if(qL<=L&&R<=qR)return minv[o];
if(qL<=M){ans = min(ans,queryMinv(o*2,L,M));}
if(M<qR) {ans = min(ans,queryMinv(o*2+1,M+1,R));}
return ans;
}
ll queryMax(ll o,ll L,ll R){
ll M = L + (R-L)/2,ans = -INF;
if(qL<=L&&R<=qR)return maxv[o];
if(qL<=M){ans = max(ans,queryMax(o*2,L,M));};
if(M<qR) {ans = max(ans,queryMax(o*2+1,M+1,R));}
return ans;
};
ll querySum(ll o,ll L,ll R){
ll M = L + (R-L)/2,ans = 0;
if(qL<=L&&R<=qR)return ans = sumv[o];
if(qL<=M){ans= ans +querySum(o*2,L,M) ;};
if(M<qR) {ans = ans+querySum(o*2+1,M+1,R);}
return ans;
}
};
segTree tree;
void work(){
ll n;
scanf("%lld",&n);
ll m;
scanf("%lld",&m);
int op;
for(int i =0;i<m;i++){
scanf("%d",&op);
if(op==0){
scanf("%lld%lld",&p,&v);
tree.update(1,1,n);
}else{
scanf("%lld%lld",&qL,&qR);
ll sum=tree.querySum(1,1,n);
ll maxv = tree.queryMax(1,1,n);
ll minv = tree.queryMinv(1,1,n);
long long ans =sum -maxv-minv;
// test3(sum,maxv,minv);
printf("%lld\n",ans);
}
}
}
int main(){
#ifdef local
freopen("in.txt","r",stdin);
#endif
work();
}