noip2012 开车旅行 set+倍增

来源:互联网 发布:2017网络教育专升本 编辑:程序博客网 时间:2024/05/04 08:24

因为要快速查找向后跳应该是哪一个点,所以用set,迭代器左右晃一下查找最接近的两个元素(P选手是不是只能用平衡树~)。然后用倍增记录i节点跳2^j步后,A和B分别走的距离。具体的细节和统计答案也需要注意。

#include<iostream>#include<cstdio>#include<cmath>#include<set>#include<map>#include<algorithm>#define maxn 100005#define LL long longusing namespace std;set<LL> Set;set<LL>::iterator it,pre,nxt;map<LL,int> id;int fa[maxn][20];int tt[maxn];LL dis[maxn][20][2];LL dp[maxn][2];void read(LL &a){    a=0;LL f=1;    char c=getchar();    while(c<'0'||c>'9')    {        if(c=='-')f=-1;        c=getchar();    }    while(c>='0'&&c<='9')    {        a*=10;a+=c-'0';        c=getchar();    }a*=f;}LL H[maxn];int n,cnt;LL inf=1e10;struct str{    int id;LL key,num;}sor[6];bool cid(str A,str B){    if(A.key!=B.key)        return A.key<B.key;    return A.num<B.num;}void init(){    scanf("%d",&n);    for(int i=1;i<=n;i++)    {        read(H[i]);        Set.insert(H[i]);        id[H[i]]=i;    }    for(int i=1;i<n;i++)    {        nxt=pre=it=Set.find(H[i]);        cnt=0;        nxt++;        if(nxt!=Set.end())        {            LL N1=*nxt;int n1=id[N1];            sor[++cnt].key=abs(N1-H[i]),sor[cnt].id=n1,sor[cnt].num=N1;            nxt++;            if(nxt!=Set.end())            {                LL N2=*nxt;int n2=id[N2];                sor[++cnt].key=abs(N2-H[i]),sor[cnt].id=n2,sor[cnt].num=N2;            }        }        if(it!=Set.begin())        {            pre--;LL P1=*pre;int p1=id[P1];            sor[++cnt].key=abs(P1-H[i]),sor[cnt].id=p1,sor[cnt].num=P1;            if(pre!=Set.begin())            {                pre--;LL P2=*pre;int p2=id[P2];                sor[++cnt].key=abs(P2-H[i]),sor[cnt].id=p2,sor[cnt].num=P2;            }        }        sort(sor+1,sor+cnt+1,cid);        int j=sor[1].id;        if(cnt>0)        {            tt[i]=j;            dis[i][0][1]=(LL)sor[1].key;        }        j=sor[2].id;        if(cnt>1)        {            fa[i][0]=j;            dis[i][0][0]=(LL)sor[2].key;        }        Set.erase(H[i]);        id[H[i]]=0;    }    for(int j=1;j<=18;j++)    for(int i=1;i<n;i++)    {        if(j==1)        {            fa[i][j]=tt[fa[i][0]];            dis[i][j][0]=dis[i][0][0];            dis[i][j][1]=dis[fa[i][0]][0][1];        }        else        {            fa[i][j]=fa[fa[i][j-1]][j-1];            if(fa[i][j])            {                dis[i][j][0]=dis[i][j-1][0]+dis[fa[i][j-1]][j-1][0];                dis[i][j][1]=dis[i][j-1][1]+dis[fa[i][j-1]][j-1][1];            }        }    }}struct Ans{    LL da,db;};Ans calc(int i,LL x){    Ans r;    LL d=0,da=0,db=0;int u=i;    for(int j=18;j>=1;j--)    {        if(dis[u][j][1]||dis[u][j][0])        if(dis[u][j][1]+dis[u][j][0]+d<=x)        {            da+=dis[u][j][0];            db+=dis[u][j][1];            d=da+db;            u=fa[u][j];        }    }    if(dis[u][0][0]+d<=x) da+=dis[u][0][0];    r.da=da;r.db=db;    return r;}int main(){    init();    LL fz=inf,fm=0,x,da,db;    int pos=0;cin>>x;    for(int i=1;i<=n;i++)    {        Ans r=calc(i,x);        da=r.da;db=r.db;        if(da*fm<fz*db&&da!=0)        {fz=da;fm=db;pos=i;}        else if(da!=0&&da*fm==fz*db&&H[pos]<H[i])        {fz=da;fm=db;pos=i;}        if(da==0&&fm==0&&H[pos]<H[i])        {fz=da;fm=db;pos=i;}    }    cout<<pos<<endl;    int m;scanf("%d",&m);    for(int i=1;i<=m;i++)    {        int s;scanf("%d",&s);        LL x;read(x);        Ans r=calc(s,x);        printf("%lld %lld\n",r.da,r.db);    }    return 0;}
2 0
原创粉丝点击