I Hate It
分块解法:
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <queue>
#include <set>
#include <map>
#include <algorithm>
#include <math.h>
#include <vector>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int maxn=2e5+10;
int block;//块的大小
int belong[maxn];//belong[i]表示i属于那一块
int l[maxn],r[maxn];//表示这块的左端点的位置和右端点的位置
int num;//块的个数
int n,m;
ll a[maxn];
ll Max[maxn];
void build(){
block=sqrt(n);
num=n/block;if (n%block)num++;
for (int i=1;i<=num;i++){
l[i]=(i-1)*block+1; r[i]=i*block;//每个块的左右端点的位置
}
r[num]=n;
for (int i=1;i<=n;i++){
belong[i]=(i-1)/block+1;
}
//---------上面是预处理
//下面根据题目进行预处理
for (int i=1;i<=num;i++){
Max[i]=0;
for (int j=l[i];j<=r[i];j++){
Max[i]=max(Max[i],a[j]);
}
}
}
void update(int pos,int val){
a[pos]=val;
Max[belong[pos]]=max(Max[belong[pos]],a[pos]);
}
ll query(int x,int y){
ll ans = 0;
if (belong[x]==belong[y]){//同属一块直接暴力
for (int i=x;i<=y;i++)ans = max(ans,a[i]);
return ans;
}
for (int i=x;i<=r[belong[x]];i++){//左边 多出部分
ans=max(ans,a[i]);
}
for (int i=belong[x]+1;i<belong[y];i++){//中间的块
ans=max(ans,Max[i]);
}
for (int i=l[belong[y]];i<=y;i++){//右边多出部分
ans = max (ans,a[i]);
}
return ans;
}
char s[10];
int main()
{
while (scanf ("%d%d",&n,&m)!=EOF){
for (int i=1;i<=n;i++){
scanf ("%lld",&a[i]);
}
build();
int x,y;
while (m--){
scanf ("%s",s);
scanf ("%d%d",&x,&y);
if (s[0]=='U'){
update(x,y);
}else {
printf ("%lld\n",query(x,y));
}
}
}
return 0;
}
线段树解法
#include<iostream>
#include<string>
#include<cstdio>
#include<cstring>
#include<vector>
#include<math.h>
#include<queue>
#include<algorithm>
using namespace std;
int n,m;
int Max[200005*4];
void build_tree(int node,int left,int right){
if (left==right){
scanf ("%d",&Max[node]);
}
else {
int mid=(left+right)>>1;
build_tree(node*2,left,mid);
build_tree(node*2+1,mid+1,right);
Max[node]=max(Max[node*2],Max[node*2+1]);
}
}
int ql,qr;
int query(int node,int left,int right){
int ans=-1;
int mid=(left+right)/2;
if (ql<=left&&right<=qr) return Max[node];
if (qr<=mid) return query(node*2,left,mid);
else if (ql>mid) return query(node*2+1,mid+1,right);
else {
return max(query(node*2,left,mid),query(node*2+1,mid+1,right));
}
}
int val;//将分数改为该值
int place;//学生的位置
void update(int node,int left,int right){
int mid=(left+right)/2;
if (left==right) Max[node]=val;
else {
if (place<=mid){
update(node*2,left,mid);
}
else {
update(node*2+1,mid+1,right);
}
Max[node]=max(Max[node*2],Max[node*2+1]);
}
}
int main ()
{
while (scanf ("%d%d",&n,&m)!=EOF){
build_tree(1,1,n);
char order[10];
for (int i=0;i<m;i++){
scanf ("%s",order);
if (order[0]=='Q'){
int a,b;
scanf ("%d%d",&ql,&qr);
printf ("%d\n",query(1,1,n));
}
else if (order[0]=='U'){
scanf ("%d%d",&place,&val);
update(1,1,n);
}
}
}
return 0;
}