http://acm.hust.edu.cn/vjudge/contest/view.action?cid=78124#problem/T
//想看题目的@willinglive
一开始一点思路都没有啊。。。后来发现我们可以倒着枚举第一堆。然后第二堆和第三堆某个数字出现的位置分别记录为x和y。维护点集(x,y)所形成的折线就可以在枚举第一堆同时更新ans
那么怎么维护呢?这就像动态凸包。支持加点操作。那么用个set维护就好了。然后最值我是用priority_queue维护的。用一个map维护top的元素可不可取。不可取就弹出
set还是各种不熟练。结果写了蛮久的。最后边界情况也对拍了才发现。有的弹出后并没有在map中去除。
据说两个set就可以维护了。。我这样做复杂度上多了一个log
感觉这完全不像是自己写出来的程序。。
#include<map>
#include<set>
#include<queue>
#include<vector>
#include<cstdio>
#include<algorithm>
using namespace std;
map <pair<int,int>,bool> M;
struct number
{
int x,p;
bool operator <(number xx) const
{
return x<xx.x;
}
}t[1000001];
struct point
{
int x,y;
int p;
bool operator <(point xx) const
{
return x<xx.x;
}
};
struct ansx
{
int p1,p2;
int x;
bool operator <(ansx xx) const
{
return x>xx.x;
}
};
set<point> S;
priority_queue <ansx> Q;
bool v[1000001];
int a[100001],b[100001],c[100001];
int f[300005],fx[300005];
int mx[300005][4];
inline void add(int x,int y,int xx)
{
point p;
p.x=x;
p.y=y;
p.p=xx;
if(p.x==0)
p.x=2100000000;
if(p.y==0)
p.y=2100000000;
set<point>::iterator it=S.lower_bound(p);
it--;
int i;
// point xt=*it;
set<point>::iterator itt=it;
set<point>::iterator itx=it;
itt++;
itx--;
while((*it).y<p.y)
{
M[make_pair((*it).p,(*itt).p)]=false;
M[make_pair((*itx).p,(*it).p)]=false;
S.erase(it--);
itx--;
M[make_pair((*it).p,(*itt).p)]=true;
}
it=S.upper_bound(p);
// xt=*it;
if(it==S.end())
{
it--;
if((*it).y>p.y)
return ;
int tt=(*it).p;
S.erase(it);
S.insert(p);
it=S.end();
it--;
it--;
// point xx=*it;
ansx xt;
xt.p1=(*it).p;
xt.p2=p.p;
xt.x=(*it).x+p.y;
M[make_pair((*it).p,p.p)]=true;
Q.push(xt);
M[make_pair((*it).p,tt)]=false;
return ;
}
if((*it).y<p.y)
{
ansx xt;
xt.p1=p.p;
xt.p2=(*it).p;
int tt=(*it).p;
xt.x=p.x+(*it).y;
M[make_pair(p.p,tt)]=true;
Q.push(xt);
it=S.lower_bound(p);
it--;
xt.p1=(*it).p;
xt.p2=p.p;
xt.x=(*it).x+p.y;
M[make_pair((*it).p,p.p)]=true;
Q.push(xt);
M[make_pair((*it).p,tt)]=false;
S.insert(p);
}
}
int main()
{
// freopen("data.in","r",stdin);
// freopen("data.out","w",stdout);
int n;
scanf("%d",&n);
int i;
int pp=0;
for(i=1;i<=n;i++)
{
scanf("%d",&a[i]);
pp++;
t[pp].x=a[i];
t[pp].p=pp;
}
for(i=1;i<=n;i++)
{
scanf("%d",&b[i]);
pp++;
t[pp].x=b[i];
t[pp].p=pp;
}
for(i=1;i<=n;i++)
{
scanf("%d",&c[i]);
pp++;
t[pp].x=c[i];
t[pp].p=pp;
}
sort(t+1,t+1+pp);
int p=0;
for(i=1;i<=pp;i++)
{
if(t[i].x!=t[i-1].x)
{
p++;
f[p]=t[i].x;
}
fx[t[i].p]=p;
}
for(i=1;i<=n;i++)
{
a[i]=fx[i];
b[i]=fx[i+n];
c[i]=fx[i+n*2];
}
for(i=1;i<=n;i++)
{
if(mx[fx[i]][1]==0)
mx[fx[i]][1]=i;
if(mx[fx[i+n]][2]==0)
mx[fx[i+n]][2]=i;
if(mx[fx[i+n*2]][3]==0)
mx[fx[i+n*2]][3]=i;
}
for(i=1;i<=n;i++)
v[a[i]]=true;
point px;
px.x=0;
px.y=2100000000;
px.p=0;
S.insert(px);
px.x=2100000000;
px.y=0;
S.insert(px);
M[make_pair(0,0)]=true;
ansx xtt;
xtt.p1=0;
xtt.p2=0;
xtt.x=0;
Q.push(xtt);
for(i=1;i<=p;i++)
if(!v[i])
add(mx[i][2],mx[i][3],i);
while(!M[make_pair(Q.top().p1,Q.top().p2)])
Q.pop();
int ans=n+Q.top().x;
for(i=n;i>=1;i--)
{
if(mx[a[i]][1]==i&&mx[a[i]][2]==0&&mx[a[i]][3]==0)
break;
if(mx[a[i]][1]==i)
{
add(mx[a[i]][2],mx[a[i]][3],a[i]);
//ansx xt=Q.top();
while(!M[make_pair(Q.top().p1,Q.top().p2)])
// {
Q.pop();
// xt=Q.top();
//}
ans=min(ans,i-1+Q.top().x);
}
else
{
while(!M[make_pair(Q.top().p1,Q.top().p2)])
Q.pop();
ans=min(ans,i-1+Q.top().x);
}
}
printf("%d\n",ans);
return 0;
}