原题请见题目链接
1. 暴力求解
这是我们线下水题赛的T1 这里为初学者提供一个思路,假设我们现在刚入OI,在考场上如何怎么优雅的避免保灵
显然 我们只要用一个 \(O(n)\) 的暴力去扫描就行了,但是直接向后扫 \(i+1,i+2\) 这样走很容易寄。因为你在\(i+1\) 跳的时候很容易把后面跳过了 ,导致你的最长序列会至少-2(我看别的题解都没有说明 应该是太简单了吧 )
那这样我们就可以初步得出这个暴力来对拍了。
我们只需定义一个 \(flag\) 来暂时保存你现在的长度 只要你扫描到 \(i-1,i-2\) 都比这个 \(i\) 大 ,即为不合法。我们在清零之前我们和 \(ans\) 取一个 \(max\) 即可
#define _for(i,a,b) for(int (i) = (a); i <= (b); i++)
using namespace std;
int a[200006];
int n, q;
int main( ) {
scanf("%d%d",&n,&q);
_for(i,1,n) scanf("%d",&a[i]);
while(q--)
{
int l,r;
int maxn = 0,flag = 0;
scanf("%d%d",&l,&r);
_for(i,l,r)
{ flag ++;
if(a[i] <= a[i - 1] && a[i - 1 ] <= a[i - 2] && i >= 3)
{ flag--; }
maxn = max(maxn,flag);
}
printf("%d\n",maxn);
}
//fclose(stdin);fclose(stdout);
}
之后你就会看到如下的情况
好消息! 没有爆零!
这时候我们就要考虑正解怎么做了
2. 前缀数组的做法
Q:为什么我们这道题可以用前缀数组去做呢 为什么想到这里呢?
ans:因为这个玩意是可以共享给后面的。假设你 \(l\) 与 \(l + r\) 中间没有任何一个违反规则的三元组,那么你可以很快的求出 \([l,l+2]\) 的长度就为 \([l,l+r] - [l+3,l+r]\) 所以我们可以用前缀的思想求解。
这里我们求出里面违反规则的 \(length\) 用 \(R-l+1-ans\) 即可
这里附上ac代码
#define _for(i,a,b) for(int (i) = (a); i <= (b); i++)
using namespace std;
int a[200006],c[2000006],b,cnt;
int n, q;
int main( )
{
// freopen("a.txt","r",stdin);
// freopen("out.txt","w",stdout);
scanf("%d%d",&n,&q);
bool flag = 1;
int b;
_for(i,1,n) {
scanf("%d",&c[i]);
if(i >= 3)
{
b = 0;
if(c[i] <= c[i - 1] && c[i - 1] <= c[i - 2])
b = 1;
a[i] += a[i -1] + b;
}
}
while(q--)
{
int l,r;
int maxn;
scanf("%d%d",&l,&r);
maxn = a[r] - a[l+1];
if(r-l+1 <= 2) maxn = r-l+1;
else maxn = r-l+1-maxn;
printf("%d\n",maxn);
}
fclose(stdin);fclose(stdout);
标签:前缀,题解,flag,maxn,ans,我们 From: https://www.cnblogs.com/mhunice/p/17456473.htmlc[i] 为原始序列 ,a[i] 保存的是违反规则的数的个数