您的位置:首页 > Web前端

UVA 1471(p242)----Defense Lines

2016-03-10 21:19 387 查看
#include<bits/stdc++.h>
#define debu
using namespace std;
const int maxn=2*1e5+50;
const int INF=1e9+50;
struct point
{
int w,g;
point(int a=0,int b=0):w(a),g(b) {}
bool operator < (const point& rhs) const
{
return w<rhs.w;
}
};
int n;
set<point> s;
int a[maxn],f[maxn],g[maxn];
void prepare()
{
a[0]=INF;
for(int i=0; i<=n; i++) f[i]=1;
for(int i=n; i>=1; i--)
if(a[i-1]<a[i]) f[i-1]+=f[i];
for(int i=0; i<=n; i++) g[i]=1;
for(int i=1; i<=n; i++)
if(a[i]>a[i-1]) g[i]+=g[i-1];
}
void solve()
{
int ans=1;
point tmp(a[1],g[1]);
s.insert(tmp);
for(int i=2; i<=n; i++)
{
point tmp(a[i],g[i]);
set<point>::iterator it=s.lower_bound(tmp);
int flag=1;
if(it!=s.begin())
{
it--;
int len=(*it).g;
ans=max(ans,len+f[i]);
if((*it).g>=g[i]) flag=0;
}
if(flag)
{
s.insert(tmp);
it=s.find(tmp);
it++;
while(it!=s.end()&&(*it).g<=g[i]&&(*it).w>=a[i]) s.erase(it++);
}
}
printf("%d\n",ans);
}
int main()
{
#ifdef debug
freopen("in.in","r",stdin);
#endif // debug
int t;
scanf("%d",&t);
while(t--)
{
s.clear();
scanf("%d",&n);
for(int i=1; i<=n; i++)
scanf("%d",&a[i]);
prepare();
solve();
}
return 0;
}

题目地址:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4217

题解:f[i]表示以i开始的最长递增连续序列,g[i]表示以i结尾的最长递增连续序列,则ans=max{g[j]+f[i]}(j<=i)。如枚举i,j,时间无法承受。所以只枚举i,快速找一个j,使得a[j]<a[i],,j<=i且g[j]应尽量大。注意到当a[i]>a[j]且g[i]<=g[j]时,g[i]一定不为最优,应舍去。set中元素有序且自带lower_bound,所以使用set。每次检测是否应该插入元素a[i],若可以,则插入后不断检测插入后位置的元素是否应该舍去。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: