BZOJ 4412/Usaco2016 Feb Circular Barn(构造)

来源:互联网 发布:用友软件打印凭证设置 编辑:程序博客网 时间:2024/05/16 11:33

思路
一下是来自lxe神犇的写法:
首先我们先破环成链。。。
将所有的值减掉1剩下的就表示多出来的
由于每次都是往顺时针方向走(一开始看错题了)因此我们找到一个能够扩展到最远的起点
即不会有其他的牛走过这里 证明yy一下 暂时写不出来
于是我们先求一个最大的连续子段和 找到起点 然后暴力往下推就行了
顺便一提的是 (x+y)^2>x^2+y^2;
所以如果一个位置有牛 且新来一只 需要替换一下接着走;

#include<iostream>#include<cstdio>#include<cstdlib>#include<algorithm>#include<cmath>#include<cstring>#include<string>#include<queue>#include<vector>using namespace std;typedef long long LL;const int imax=1000000+229;int n,a[imax*2]; LL sum[imax]; void iread(){    scanf("%d",&n);    for(int i=1;i<=n;i++) scanf("%d",&a[i]),a[n+i]=a[i]; }int lishi[imax*2],x[imax*2];int inext(int x){ ++x; if(x<=2*n) return x; else return 1;}void iwork(){    int temp=0; int begin=0; int last=0; int Max=0;     for(int i=1;i<=n*2;i++) lishi[i]=a[i]-1;    for(int i=1;i<=n*2;i++)     {        temp+=lishi[i];        if(temp>Max) { Max=temp; begin=last;}            if(temp<0) { temp=0; last=i+1; }     }//  printf("%d\n",begin);    int tot=1;    if(begin>n) begin-=n;     for(int i=begin;tot<=n;i=inext(i)) x[tot++]=lishi[i];    tot--;    for(int i=1;i<=n;i++) sum[i]=sum[i-1]+(LL)i*i;//  for(int i=1;i<=tot;i++) printf("%d\n",x[i]);    int k=1; LL ans=0;     ans+=sum[x[1]]; k+=x[1];    for(int i=2;i<=n;i++)    {        if(k>=i) x[i]++;        if(x[i]>0)        {            if(k<i) k=i;            int pos=k+x[i];            ans+=(sum[pos-i]-sum[k-i]);            k=pos;              }    }    printf("%lld\n",ans);}int main(){//  freopen("p3.in","r",stdin);     iread();    iwork();    return 0;}
1 0
原创粉丝点击