HNOI 2013 bzoj 3141 旅行

这个题目我不会看别人的代码,那个正负问题我给满分

/**************************************************************
    Problem: 3141
    User: Clare
    Language: C++
    Result: Accepted
    Time:1872 ms
    Memory:54008 kb
****************************************************************/
 
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
#include <vector>
using namespace std;
 
#define N 500010
 
int n,m,tot,Ans;
int sum[N],A[N],num[N];
struct Node{
    int l,r,x;
}line[N<<2];
struct My_queue{
    int head,tail,len;
    My_queue(){head=tail=len=0;}
    bool Empty(){return !len;}
    int New_node(int l,int r,int x){
        line[++tot]=(Node){l,r,x};
        return tot;
    }
    int Top(){return line[head].x;}
    int Back(){return line[tail].x;}
    void Pop_Top(){head=line[head].r;len--;}
    void Pop_Back(){tail=line[tail].l;len--;}
    void Push_back(int x){
        if(len==0)
            head=tail=New_node(0,0,x);
        else line[tail].r=New_node(tail,0,x),tail=line[tail].r;
        len++;
    }
    void Push(int x){
        while(len&&A[Back()]>A[x])
            Pop_Back();
        Push_back(x);
    }
}q1[N<<1],q2[N<<1],*Q1=q1+N,*Q2=q2+N;
 
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
 
void Solve()
{
    if(sum[1]==0)
        Ans=num[1]<m?1:0;
    else
        Ans=ceil(1.0*abs(sum[1])/m);
    num[n+1]=-1;
    if(Ans==0)
    {
        int now=2;
        for(int i=1;i<m;i++)
        {
            while(num[now+1]>=m-i)
            {
                if(sum[now+1]==0)
                    Q1[0].Push(now);
                now++;
            }
            printf("%d ",A[Q1[0].Top()]);
            Q1[0].Pop_Top();
        }
        printf("%d\n",A[n]);
    }
    else
    {
        for(int i=1;i<n;i++)
            Q2[sum[i+1]].Push_back(i);
        int Last=0;A[n+1]=n+1;
        for(int i=1;i<m;i++)
        {
            int Min=n+1;
            for(int j=sum[Last+1]-Ans;j<=sum[Last+1]+Ans;j++)
            {
                if(ceil(1.0*abs(j)/(m-i))>Ans)
                    continue;
                while(!Q2[j].Empty())
                {
                    int now=Q2[j].Top();
                    if(n-now<m-i)
                        break;
                    if(now>Last)
                        Q1[j].Push(now);
                    Q2[j].Pop_Top();
                }
                while(!Q1[j].Empty()&&Q1[j].Top()<=Last)
                    Q1[j].Pop_Top();
                if(!Q1[j].Empty())
                {
                    if(A[Min]>A[Q1[j].Top()])
                        Min=Q1[j].Top();
                }
            }
            Last=Min;
            printf("%d ",A[Min]);
        }
        printf("%d\n",A[n]);
    }
}
 
int main()
{
    n=read();m=read();
    for(int i=1;i<=n;i++)
    {
        A[i]=read();sum[i]=read();
        if(!sum[i])
            sum[i]=-1;
    }
    for(int i=n-1;i>=1;i--)
        sum[i]+=sum[i+1];
    for(int i=n;i>=1;i--)
        num[i]=num[i+1]+((sum[i]==0)?1:0);
    Solve();
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值