• 【NOIP2016提高组】 Day2 T2 蚯蚓


    题目传送门:https://www.luogu.org/problemnew/show/P2827

    自测时被题面所误导...,题面中说逢t的倍数才输出答案,以为有什么玄妙的方法直接将m次操作变成了m/t次操作。结果GG....

    65分做法:写一个左偏树,每次取出最顶端元素,对堆中其余元素全部+q(可以用标记完成),将该元素取出后,切为两段后再丢入该树中。时间复杂度为O((m+n) log m)。

    幸好我不会65分的STL做法,据说此题有人用STL被卡了5分.....

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<queue>
     4 #include<cstring>
     5 #define M 1100000
     6 using namespace std;
     7 priority_queue<int> Q;
     8 int n,m,q,t;
     9 int tag[M]={0},a[M]={0},lc[M]={0},rc[M]={0};
    10 
    11 void pushdown(int x){
    12     if(!tag[x]) return;
    13     tag[lc[x]]+=tag[x]; tag[rc[x]]+=tag[x];
    14     a[lc[x]]+=tag[x]; a[rc[x]]+=tag[x];
    15     tag[x]=0;
    16 }
    17 int merge(int x,int y){
    18     if(!x) return y;
    19     if(!y) return x;
    20     if(a[x]>a[y]){
    21         pushdown(x);
    22         rc[x]=merge(rc[x],y);
    23         swap(lc[x],rc[x]);
    24         return x;
    25     }else{
    26         pushdown(y);
    27         lc[y]=merge(x,lc[y]);
    28         swap(lc[y],rc[y]);
    29         return y;
    30     }
    31 }
    32 int rt=0,use=0;
    33 long long v,u;
    34 int main(){
    35     freopen("earthworm.in","r",stdin);
    36     freopen("earthworm.out","w",stdout);
    37     cin>>n>>m>>q>>u>>v>>t;
    38     for(int i=1;i<=n;i++){
    39         int x; scanf("%d",&x);
    40         use++; a[use]=x;
    41         rt=merge(use,rt);
    42     }
    43     for(int i=1;i<=m;i++){
    44         int x=a[rt],lastrt=rt;
    45         rt=merge(lc[rt],rc[rt]);
    46         tag[rt]+=q; a[rt]+=q;
    47         if(i%t==0) printf("%d ",x);
    48         int x1=(u*x)/v,x2=x-x1;
    49         lc[lastrt]=rc[lastrt]=0; a[lastrt]=x1; 
    50         rt=merge(rt,lastrt);
    51         use++; a[use]=x2;
    52         rt=merge(use,rt);
    53     }
    54     printf("
    ");
    55     for(int i=1;i<=m+n;i++){
    56         int x=a[rt]; rt=merge(lc[rt],rc[rt]);
    57         if(i%t==0) printf("%d ",x);
    58     }
    59     printf("
    ");
    60 }
    很垃圾的65分代码

    下面说下100%的做法。

    首先,先开三个队列,x,y,z。初始状态下,队列x中保存的是完全没有被切过的蚯蚓的长度(初始时排个序,最大的在最前面),队列y中保存一条被切开的蚯蚓前半部分的长度,队列z中保存一条被切开的蚯蚓的后半部分的长度。我们需保证y,z中元素的单调递减性。

    不妨设q=0。由于p=[0,1],则有x[1]≥y[1],z[1]。又因x[i]≥x[i-1],则有y[i]≥y[i-1],z[i]≥z[i-1]。我们每次在x,y,z三个队列的头部取出长度最长的蚯蚓,随后将其分为两半后,分别直接加至y队列和z队列末尾,基于上述性质,无需排序或树结构维护y,z的单调性。

    这种方法已经可以拿90分了...

    实际上,当q≠0时,通过一些小的操作,y,z的单调性依然能够满足。

    假设当前时间为t,若取出元素入队的时间为t0,入队时长度为x,则出队长度为q(t-t0)+x。我们修改下元素入队的规则,假设当前需要将x入队,则在x入队前,将x减去q*t0,再加入队列中。不难证明该方法可以保证y,z队列依然满足单调性。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #define L long long
     6 #include<queue>
     7 #define INF 1231231231
     8 #define M 10000010
     9 using namespace std;
    10 int x[M]={0},y[M]={0},z[M]={0};int a[M]={0},b[M]={0};
    11 int u,v,q,t,h1=0,h2=0,h3=0,t1=0,t2=0,t3=0; int n,m;
    12 int main(){
    13     freopen("earthworm.in","r",stdin);
    14     freopen("earthworm.out","w",stdout);
    15     scanf("%d%d%d%d%d%d",&n,&m,&q,&u,&v,&t);
    16     for(int i=1;i<=n;i++) scanf("%d",a+i);
    17     sort(a+1,a+n+1);
    18     for(int i=n;i;i--) x[t1++]=a[i];
    19     for(int i=1,pls=0;i<=m;i++){
    20         int tmp=-INF,id=1;
    21         if(h1<t1) if(tmp<x[h1]) tmp=x[h1],id=1;
    22         if(h2<t2) if(tmp<y[h2]) tmp=y[h2],id=2;
    23         if(h3<t3) if(tmp<z[h3]) tmp=z[h3],id=3;
    24         tmp+=pls; pls+=q;
    25         if(i%t==0) printf("%d ",tmp);
    26         if(id==1) h1++; if(id==2) h2++; if(id==3) h3++;
    27         L y1=((L)tmp*u)/v,z1=tmp-y1;
    28         y[t2++]=(y1-pls); z[t3++]=(z1-pls);
    29     }
    30     int pls=(m)*q; printf("
    ");
    31     for(int i=1;i<=n+m;i++){
    32         int tmp=-INF,id=1;
    33         if(h1<t1) if(tmp<x[h1]) tmp=x[h1],id=1;
    34         if(h2<t2) if(tmp<y[h2]) tmp=y[h2],id=2;
    35         if(h3<t3) if(tmp<z[h3]) tmp=z[h3],id=3;
    36         tmp+=pls; if(i%t==0) printf("%d ",tmp); //b[i]=tmp;
    37         if(id==1) h1++; if(id==2) h2++; if(id==3) h3++;
    38     }
    39     //for(int i=1;i<=n+m;i++) printf("%lld ",b[i]);
    40 }
  • 相关阅读:
    TCP通过哪些措施,保证传输可靠
    http协议---简述
    单播、广播、组播、多播
    axios 设置超时时间 timeout
    axios 处理并发请求
    vue 模板语法
    vue keep-alive
    v-if 条件渲染分组
    debounce 防抖动函数
    vue scoped 深度作用选择器
  • 原文地址:https://www.cnblogs.com/xiefengze1/p/7725495.html
Copyright © 2020-2023  润新知