3 条题解

  • 7
    @ 2024-11-18 13:51:23

    题面 kawa

    容易发现 nnnn 列的面包卷从最下面一行开始可以划分成一个 n+(n1)+(n1)+(n2)+(n2)+...+1+1n+(n-1)+(n-1)+(n-2)+(n-2)+...+1+1 的形式,一共有 2n12n-1 个面包块。将这些面包块编号,每 44 个一循环,第一和第三个分别是区间正着和倒着加等差数列,第二和第四个是单点加等差数列。

    区间加等差数列的部分考虑做两次前缀和。用正着的情况举例。第一次将 ll 加一,r+1r+1 减一,然后做一次前缀和,完成区间加一。第二次前缀和将 r+1r+1 减去区间长度,消去其对后续位置的影响。正着加和倒着加分开做。

    始末位置和实现细节见代码。

    跑得没 spq 快

    #include<bits/stdc++.h>
    #define ll long long
    #define ull unsigned long long
    #define uint unsigned int 
    #define DU double
    #define PII pair<int,int>
    #define PLL pair<ll,ll>
    #define rep(i,x,n) for(int i=(x);i<=(n);i++)
    #define nep(i,x,n) for(int i=(x);i>=(n);i--)
    using namespace std;
    const int N=2e5+10;
    ll n,k,a[N],s[N],ssl[N],ssr[N],ssl2[N],ssr2[N];
    inline void getans(ll x,ll y,ll now){
    	if(x>k) return ;
    	if(y%4==1){
    		ll l=y/4+1,r=min(l+k-x,n-l+1);
    		s[l]+=x-1,s[r+1]-=x-1;
    		ssl[l]++,ssl[r+1]--,ssl2[r+1]-=r-l+1;
    	}
    	if(y%4==2){
    		ll l=x,r=min(k,x+now-1),pos=n-(y/4);
    		a[pos]+=(l+r)*(r-l+1)/2;
    	}
    	if(y%4==3){
    		ll r=n-y/4-1,l=max(r-(k-x),y/4+1);
    		s[l]+=x-1,s[r+1]-=x-1;
    		ssr[r]++,ssr[l-1]--,ssr2[l-1]-=r-l+1;
    	}
    	if(y%4==0){
    		ll l=x,r=min(k,x+now-1),pos=y/4;
    		a[pos]+=(l+r)*(r-l+1)/2;
    	}
    	getans(x+now,y+1,now-(y&1));
    }
    int main(){
    	scanf("%lld%lld",&n,&k);
    	getans(1,1,n);
    	rep(i,1,n) s[i]+=s[i-1];
    
    	rep(i,1,n) ssl[i]+=ssl[i-1];
    	rep(i,1,n) ssl[i]=ssl[i]+ssl2[i];
    	rep(i,1,n) ssl[i]+=ssl[i-1];
    
    	nep(i,n,1) ssr[i]+=ssr[i+1];
    	nep(i,n,1) ssr[i]=ssr[i]+ssr2[i];
    	nep(i,n,1) ssr[i]+=ssr[i+1];
    
    	rep(i,1,n) printf("%lld ",a[i]+s[i]+ssl[i]+ssr[i]);puts("");
    	return 0;
    }
    
    • @ 2024-11-18 14:02:29

      @ woc 为什么我动不了你的评论(

    • @ 2024-11-18 14:02:42

      @ 权限比屋檐了

信息

ID
16
时间
1000ms
内存
256MiB
难度
8
标签
(无)
递交数
58
已通过
10
上传者