给定10^5个数,区间查询严格上升的最长连续序列长度,点更新某个数. | 线段树,区间合并 有三个数组,msum, lsum, rsum,分别存总最长,左端串长,右端串长 一直错的一个地方是:query中,合并的时候,若左右儿子可以合并,应该取max{min[左儿子右长,实际右长],min[右儿子左长,实际左长]},而不是max{min[左儿子最大长,实际右长],min[右儿子最大长,实际左长]}.因为有可能儿子最大长并不是由中间接上的那一段产生的 这种细节非常复杂的题分析清楚算法很重要.靠Debug实在很难找.其实是原理性错误... |
#include <cstdio>
#include <cstring>
#include <cctype>
#include <algorithm>
using namespace std;
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
const int maxn = 100005;
int num[maxn];
int lsum[maxn<<2] , rsum[maxn<<2] , msum[maxn<<2];
void PushUp(int l, int r,int rt) {
lsum[rt] = lsum[rt<<1];
rsum[rt] = rsum[rt<<1|1];
int m = (l+r)>>1;
if(num[m]<num[m+1])
{
if (lsum[rt] == m - l + 1) lsum[rt] += lsum[rt<<1|1];
if (rsum[rt] == r - m) rsum[rt] += rsum[rt<<1];
msum[rt] = max(lsum[rt<<1|1] + rsum[rt<<1] , max(msum[rt<<1] , msum[rt<<1|1]));
}
else
{
msum[rt] = max(msum[rt<<1] , msum[rt<<1|1]);
}
}///总最长为左和 or 右和 or 左右拼接中间的段
void build(int l,int r,int rt) {
msum[rt] = lsum[rt] = rsum[rt] = 1;//区间长度
if (l == r) return ;
int m = (l + r) >> 1;
build(lson);
build(rson);
PushUp(l,r,rt);
}
void update(int p,int c,int l,int r,int rt) {
if (l==r) {
msum[rt] = lsum[rt] = rsum[rt] = 1;
return ;
}
int m = (l + r) >> 1;
if (p <= m) update(p , c , lson);
if (m < p) update(p , c , rson);
PushUp(l,r,rt);
}
int query(int L,int R,int l,int r,int rt) {
if(L==l&&r==R)//?
{
return msum[rt];
}
int m = (l+r)>>1;
if(R<=m)
{
return query(L, R, lson);
}
else if(L>m)
{
return query(L, R, rson);
}
else if(num[m]>=num[m+1])
{
return max(query(L, m, lson),query(m+1, R, rson));
}
else
{
int a = query(L,m,lson), b = query(m+1, R, rson);
int ls = min(rsum[rt<<1],m - L + 1), rs = min(lsum[rt<<1|1], R - m);
return max(max(a,b),ls+rs);
}
}
int main() {
int n , m, T;
scanf("%d",&T);
while (T--) {
scanf("%d %d",&n,&m);
for(int i=0;i<n;i++)
{
scanf("%d",num+i);
}
build(0 , n-1 , 1);
int a , b;
char op[2];
while(m--)
{
scanf("%s",op);
if (op[0] == 'U') {
scanf("%d %d",&a,&b);
num[a] = b;
update(a , b , 0 , n-1 , 1);
}
else {
scanf("%d %d",&a,&b);
printf("%d\n",query(a , b , 0 , n-1 , 1));
}
}
}
return 0;
}