link
s[i]为前缀和
价值为
- r−l+1 s [ r ] − s [ l − 1 ] > 0
- 0 s [ r ]-r [ l - 1]=0
- r-l+1 s[ r ] - s [ l - 1 ]<0
求最大价值和
我们就可以考虑建立权值线段树维护三个值
//线段树部分省略了
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define fer(i,a,b) for(int i=a;i<=b;i++)
const int N=2e5+10;
int a[N];
int s[N];
int dp[N];
int s1[N];
int d;
signed main()
{
int t;
cin>>t;
while(t--)
{
int n;
cin>>n;
fer(i,1,n)cin>>a[i],s[i]=s[i-1]+a[i],s1[i]=s[i];
fer(i,0,n)dp[i]=-1e9;
sort(s1,s1+n+1);
int cnt=unique(s1,s1+n+1)-s1;
fer(i,1,n) s[i]=lower_bound(s1,s1+cnt+1,s[i])-s1+1;
fer(i,0,2)
{
d=i;
build(1,1,cnt);
}
fer(i,0,2)
{
d=i;
change(1,s[0],0);
}
fer(i,1,n)
{
d=0;
dp[i]=query(1,1,s[i]-1)+i;
d=1;
dp[i]=max(dp[i],query(1,s[i],s[i]));
d=2;
dp[i]=max(dp[i],query(1,s[i+1],cnt)-i);
d=0;
change(1,s[i],dp[i]-i;);
d=1;
change(1,s[i],dp[i]);
d=2;
change(1,s[i],dp[i]+i);
}
cout<<dp[n]<<endl;
}
return 0;
}
link2
蓝桥杯省赛a组 的一道题
int main()
{
int n,k,cnt=0;
cin>>n>>k;
for(int i=1;i<=n;i++)cin>>a[i],b[++cnt]=a[i];
if(n==k)
{
cout<<n<<endl;
return 0;
}
soet(b+1,b+n+1);
cnt=unique(b+1,b+n+1)-(b+1);
for(int i=1;i<=n;i++)
{
a[i]=lower_bound(b+1,b+n+1,a[i])-b;
}
int ans=0;
build(1,1,n);
for(int i=1;i<=n;i++)
{
dp[i]=query(1,1,a[i])+1;
undate(1,a[i],dp[i]);
}
build(1,1,n);
for(i=n;i>k;i--)
{
ans=max(ans,dp[i-k]+k-1+query(1,a[i-k],cnt)+1);
int tmp=query(1,a[i],cnt)+1;
ans=max(ans,tmp);
update(1,a[i],tmp);
}
cout<<ans<<endl;
return 0;
}
青蛙过河
bool check(int mid)
{
for(int i=1;i+mid-1<=n;i++)
{
if(sum[i+mid-1]-sum[i-1]<x*2)return false;
return true;
}
}