我我我又又又...要好好学习了

放上题解

#include<iostream>
#include<fstream>
#include<algorithm>
using namespace std;
int n,M,line[100010][3],maxn = 0,x[100010],ans[100010] = {0};
struct treenode
{
 int b;int e;
 int mn;
}tree[400010];
void inittree(int l,int r,int p)
//l,r分别是每个线段的左右端点,p是指线段的编号
{
 int m;
 tree[p].b = l;
 tree[p].e = r;
 if(l == r)tree[p].mn = x[l];
 //当这个线段已经被分成大小唯一只有一个数时,对它进行赋值
 else
 {
  m = (l + r) / 2;//每次取中间值对它进行二分
  //建左线段和右线段
  inittree(l,m,p + p);
  inittree(m + 1,r,p + p + 1);
  tree[p].mn = max(tree[p + p].mn,tree[p + p + 1].mn);//在建树的过程中应随手保存最大值
 }
}
void ins(int np,int nn,int p)
//np第x位数要被修改,nn是要修改成的最大值,p线段树的编号
{
 int m;
 if(tree[p].b == tree[p].e) tree[p].mn = nn;//找到了这个只有一个数的线段后,更改它的最大值
 else
 {
  m = (tree[p].b + tree[p].e) / 2;
  if(np <= m)ins(np,nn,p + p);
  else ins(np,nn,p + p + 1);
  tree[p].mn = max(tree[p + p].mn,tree[p + p + 1].mn);//更改所有的最大值
 }
}
int calc(int p,int st,int en)
{
 int m;
 if(tree[p].b == st && tree[p].e == en)return tree[p].mn;//如果这个区间刚好卡在一个线段上,直接输出最大值
 if(tree[p].b == tree[p].e)return tree[p].mn;//如果就是一个点,那就直接输出这个点的数
 else
 {
  m = (tree[p].b + tree[p].e) / 2;//如果这个区间可以被好几个区间分隔开,那就分开找到每个区间的最大值
  if(en <= m)return calc(p + p,st,en);
  if(st > m)return calc(p + p + 1,st,en);
  return max(calc(p + p,st,m),calc(p + p + 1,m + 1,en));//比较找出最大的最大值,然后它就是答案了
 }
}
void addans(int answer)
{
 //把答案存进数组里
 ans[0]++;
 ans[ans[0]]=answer;
}
int main()
{
 int i,j;
 cin>>n;
 for(i = 1;i <= n;i++)scanf("%d",&x[i]);
 inittree(1,n,1);//建线段树
 cin>>M;
 for(i = 1;i <= M;i++)
 {
  int temp,tx,ty;
  scanf("%d %d %d",&temp,&tx,&ty);
  if(temp == 1)
  {
   ins(tx,ty,1);//修改线段树
  }
  if(temp == 2)addans(calc(1,tx,ty));//求最大值
 }
 for(i = 1;i <= ans[0];i++)printf("%d\n",ans[i]);
 return 0;
}