codeforces819B Mister B and PR Shifts -- 线段树

di 表示 i 次操作后的答案。
考虑pi dj 的贡献
ipi 时:

  • dj+=pii+j , j[0,pii]
  • dj+=ipi+j , j[pii+1,ni]
  • dj+=pii+nj , j[ni+1,n1]

pi<i

  • dj+=ipi+j , j[0,ni]
  • dj+=pii+nj , j[ni+1,n+pii]
  • dj+=ipin+j , j[ni+pi+1,n1]

di=ki+b ,枚举 p ,更新k b 就可以了。
时间复杂度O(nlogn)加了读优才过

代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
inline char nc(){
    static char buf[100000],*p1=buf,*p2=buf;
    if(p1==p2){
        p2=(p1=buf)+fread(buf,1,100000,stdin);
        if(p1==p2)return EOF;
    }
    return *p1++;
}
inline void Read(int& x){
    char c=nc();
    for(;c<'0'||c>'9';c=nc());
    for(x=0;c>='0'&&c<='9';x=(x<<3)+(x<<1)+c-48,c=nc());
}
#define N 1000010
#define ll long long
ll c[2][N<<2],p[2][N<<2],Tmp,Ans=1e18,d[N];
int i,j,k,n,m,x;
inline void Push(int x,int l){
    int l1=l+1>>1,l2=l>>1;
    if(p[0][x]){
        if(l1==1)
        c[0][x<<1]+=p[0][x];
        p[0][x<<1]+=p[0][x];
        if(l2==1)
        c[0][x<<1|1]+=p[0][x];
        p[0][x<<1|1]+=p[0][x];
        p[0][x]=0;
    }
    if(p[1][x]){
        if(l1==1)
        c[1][x<<1]+=p[1][x];
        p[1][x<<1]+=p[1][x];
        if(l2==1)
        c[1][x<<1|1]+=p[1][x];
        p[1][x<<1|1]+=p[1][x];
        p[1][x]=0;
    }
}
inline void Update(int x,int l,int r,int L,int R,int y,bool d){
    if(l>R||r<L)return;
    if(l>=L&&r<=R){
        if(l==r)c[d][x]+=y;
        p[d][x]+=y;
        return;
    }
    int Mid=l+r>>1;
    Update(x<<1,l,Mid,L,R,y,d);
    Update(x<<1|1,Mid+1,r,L,R,y,d);
}
inline void GetAns(int x,int l,int r){
    if(l==r){
        d[l]=c[0][x]+1ll*l*c[1][x];
        return;
    }
    Push(x,r-l+1);
    int Mid=l+r>>1;
    GetAns(x<<1,l,Mid);
    GetAns(x<<1|1,Mid+1,r);
}
inline void Add(int l,int r,int x,int y){
    if(l>r)return;
    Update(1,0,n-1,l,r,x,0);
    Update(1,0,n-1,l,r,y,1);
}
int main(){
    Read(n);
    for(i=1;i<=n;i++){
        Read(x);
        if(x>=i)Add(0,x-i,x-i,-1),Add(x-i+1,n-i,i-x,1),Add(n-i+1,n-1,x-i+n,-1);else
        Add(0,n-i,i-x,1),Add(n-i+1,n-i+x,x-i+n,-1),Add(n-i+x+1,n-1,i-x-n,1);
    }
    GetAns(1,0,n-1);
    for(i=0;i<n;i++)if(d[i]<Ans)Ans=d[i],x=i;
    printf("%I64d %d\n",Ans,x);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值