BZOJ3827: [Poi2014]Around the world

来源:互联网 发布:怎么登录熊片数据库 编辑:程序博客网 时间:2024/05/19 20:37

将一段延伸到尽可能接近d,设其长为L,发现n个开头的走法在这一段内都会占据L个位置中的一个,根据这个性质就可以dp了
把环拉成链,倍长,对n+1~2n做dp,st[i]表示走到i,起点是哪个点,f[i]表示st[i]走到i需要的最少步数,f[i]=min f[j]+1 (s[i]-s[j]<=d)

code:

#include<set>#include<map>#include<deque>#include<queue>#include<stack>#include<cmath>#include<ctime>#include<bitset>#include<string>#include<vector>#include<cstdio>#include<cstdlib>#include<cstring>#include<climits>#define ll long longusing namespace std;inline void read(int &x){    char c; while(!((c=getchar())>='0'&&c<='9'));    x=c-'0';    while((c=getchar())>='0'&&c<='9') (x*=10)+=c-'0';}const int maxn = 2000005;int n,m,u;int s[maxn];int f[maxn],st[maxn];int main(){    read(n); read(m);    for(int i=1;i<=n;i++)     {        int x; read(x); if(u<x)u=x;        s[i]=s[i-1]+x;    }    for(int i=n+1;i<=n+n;i++) s[i]=s[i-1]+s[i-n]-s[i-n-1];    for(int i=1;i<=n;i++) st[i]=i,f[i]=0;    while(m--)    {        int d; read(d); if(d<u) { puts("NIE");continue; }        int j=1;        for(int i=n+1;;i++)        {            while(s[i]-s[j]>d)j++;            f[i]=f[j]+1; st[i]=st[j];            if(i-st[i]>=n) { printf("%d\n",f[i]);break; }        }    }    return 0;}
原创粉丝点击