1. 程式人生 > >Luogu P2827 蚯蚓

Luogu P2827 蚯蚓

code using clu 集體 return void 差分 應該 數據

看到題目就可以想到直接開的堆模擬的過程了吧,這個還是很naive的

註意在用堆做的時候也是要明智一點的,對於蚯蚓長度的相加肯定不能直接遍歷並加上,還是可以差分一下的

其實說白了就是把集體加->單體減的一個小技巧,還是挺常用的。

然後看這個數據範圍猜想應該是有什麽\(O(n)\)的做法的,然後這就要發現題目中隱含的單調性

我們考慮講所有的蚯蚓分個類,所有初始時沒切割過的蚯蚓分為一類,每次切割產生的較長的蚯蚓分為一類,而產生的較短的蚯蚓分為一類

然後我們推到一下就可以發現,對於後面的兩類蚯蚓,它們滿足單調性

因為我們根據切割的過程可以發現:

  • 先切割的蚯蚓長度一定比後切割的蚯蚓長度長
  • 同一種切法,後切割的一定比先切割的短

所以我們再對初始的蚯蚓長度拍個序,就可以得到三個單調的隊列(註意不是單調隊列),每一次比較時我們取出隊首並切割最長的一只再丟進第二隊,第三隊即可

差分的思想還是要的,不過這裏直接記錄了每一只蚯蚓進隊的時間,每次註意加上增長的長度

細節比較多,最後對這三隊蚯蚓做一次歸並即可(因為都是有序的)

因此復雜度為\(O(n\ logn+m)\)

CODE

#include<cstdio>
#include<cctype>
#include<algorithm>
using namespace std;
const int N=100005,M=7000005;
int n,m,q,u,v,t,a[N],que[3][M],num[3][M],H[3],T[3],cut[M],ans[N+M],temp[N+M],cnt,tot;
inline char tc(void)
{
    static char fl[100000],*A=fl,*B=fl;
    return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
}
inline void read(int &x)
{
    x=0; char ch; while (!isdigit(ch=tc()));
    while (x=(x<<3)+(x<<1)+ch-‘0‘,isdigit(ch=tc()));
}
inline void write(int x)
{
    if (x>9) write(x/10);
    putchar(x%10+‘0‘);
}
inline bool cmp(int x,int y)
{
    return x>y;
}
inline void swap(int &a,int &b)
{
    int t=a; a=b; b=t;
}
inline void merge(void)
{
    register int i=H[0],j=H[1];
    while (i<=T[0]&&j<=T[1])
    if (que[0][i]+(m-num[0][i])*q>que[1][j]+(m-num[1][j])*q) temp[++cnt]=que[0][i]+(m-num[0][i])*q,++i;
    else temp[++cnt]=que[1][j]+(m-num[1][j])*q,++j;
    for (;i<=T[0];++i) temp[++cnt]=que[0][i]+(m-num[0][i])*q;
    for (;j<=T[1];++j) temp[++cnt]=que[1][j]+(m-num[1][j])*q;
    i=1; j=H[2];
    while (i<=cnt&&j<=T[2])
    if (temp[i]>que[2][j]+(m-num[2][j])*q) ans[++tot]=temp[i],++i; else ans[++tot]=que[2][j]+(m-num[2][j])*q,++j;
    for (;i<=cnt;++i) ans[++tot]=temp[i];
    for (;j<=T[2];++j) ans[++tot]=que[2][j]+(m-num[2][j])*q;
}
inline void print(void)
{
    for (register int i=t;i<=m;i+=t)
    write(cut[i]),putchar(‘ ‘); putchar(‘\n‘);
    for (register int i=t;i<=n+m;i+=t)
    write(ans[i]),putchar(‘ ‘);
}
int main()
{
    //freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
    register int i,j; read(n); read(m); read(q); read(u); read(v); read(t);
    for (i=1;i<=n;++i) read(a[i]); sort(a+1,a+n+1,cmp);
    for (i=1;i<=n;++i) que[0][++T[0]]=a[i]; H[0]=H[1]=H[2]=1;
    for (i=1;i<=m;++i)
    {
        int len=-1,id;
        for (j=0;j<3;++j) 
        if (H[j]<=T[j]) if (que[j][H[j]]+(i-num[j][H[j]]-1)*q>len) len=que[j][H[j]]+(i-num[j][H[j]]-1)*q,id=j;
        cut[i]=len; ++H[id]; int x=1LL*len*u/v,y=len-x; if (x<y) swap(x,y);
        que[1][++T[1]]=x; num[1][T[1]]=i; que[2][++T[2]]=y; num[2][T[2]]=i;
    }
    merge(); print(); return 0;
}

Luogu P2827 蚯蚓