5-14 数据结构啊poi T.三个数组的故事

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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值