2 条题解

  • 0
    @ 2026-9-2 12:02:35

    思路

    有以下结论:$\forall x_1\le x_2 \in \mathbb{Z},\lfloor px_1 \rfloor \le \lfloor px_2 \rfloor,x_1 - \lfloor px_1 \rfloor \le x_2 - \lfloor px_2 \rfloor$。
    第一个式子很显然,因为 ux=pxu_x = pxyu=uy_u = \lfloor u \rfloor 两个函数都是单调不降的。
    下面来证明第二个式子。令函数 $y_x=x - \lfloor px \rfloor = \lceil x - px \rceil = \lceil (1 - p)x \rceil$。容易发现 ux=(1p)xu_x = (1 - p)xyu=uy_u = \lceil u \rceil 两个函数也都是单调不降的,所以原函数 yx=xpxy_x=x - \lfloor px \rfloor 单调不降。
    有了这个结论,我们就知道神刀手先切的蚯蚓形成的前一半,一定比后切的蚯蚓形成的前一半要长;先切的蚯蚓形成的后一半,一定比后切的蚯蚓形成的后一半要长。
    所以可以维护三个队列,分别存初始蚯蚓切出的前半条蚯蚓切出的后半条蚯蚓。因为入队的顺序和入队的数字大小是负相关,所以三个队列都是单调的。

    对于增加量 qq,只有两条蚯蚓没长就相当于这两条蚯蚓变短了 qq。可以维护一个增长量 addadd 表示所有蚯蚓变长的长度,每次切蚯蚓的时候都把切出的蚯蚓长度减 qq
    由于每次切的时候长度都要减 qq,所以这个变长不影响队列的单调性。

    时间复杂度为 O(n+m)O(n+m)


    代码

    #include<bits/stdc++.h>
    using namespace std;
    const int inf=1e9;
    int n,m,ad,u,v,t;
    int add;
    int a[1000003];
    queue<int>q[3];
    
    int get(){
    	int mxi=-1;
    	for(int i=0;i<3;i++)
    		if(!q[i].empty()&&(mxi==-1||q[mxi].front()<q[i].front()))mxi=i;
    	int t=q[mxi].front();
    	q[mxi].pop();
    	return t;
    }
    
    int main(){
    	ios::sync_with_stdio(0);
    	cin.tie(0);cout.tie(0);
    	cin>>n>>m>>ad>>u>>v>>t;
    	for(int i=1;i<=n;i++)cin>>a[i];
    	sort(a+1,a+1+n,greater<int>());
    	for(int i=1;i<=n;i++)q[0].push(a[i]);
    	for(int i=1;i<=m;i++){
    		int x=get()+add,y;
    		if(i%t==0)cout<<x<<' ';
    		y=(long double)x*u/v;
    		x-=y;
    		add+=ad;
    		y-=add;
    		x-=add;
    		q[1].push(x);
    		q[2].push(y);
    	}
    	cout<<'\n';
    	for(int i=1;i<=n+m;i++){
    		int x=get();
    		if(i%t==0)cout<<x+add<<' ';
    	}
    	return 0;
    }
    
    • 0
      @ 2025-10-8 17:11:17

      用堆模拟的85分代码:

      #include<bits/stdc++.h>//用堆模拟的85分代码
      using namespace std;
      priority_queue<int>Q;
      int n,m,q,u,v,t;
      int main()
      {
          scanf("%d%d%d%d%d%d",&n,&m,&q,&u,&v,&t);
          double p=(double)u/v;
          for(int i=1;i<=n;i++)
          {
              int a;scanf("%d",&a);
              Q.push(a);
          }
          for(int i=1;i<=m;i++)
          {
              if(i%t==0)printf("%d ",Q.top()+(i-1)*q);
              int x=Q.top()+(i-1)*q;Q.pop();
              Q.push(floor(p*x)-i*q);
      		Q.push(x-floor(p*x)-i*q);
          }
      	printf("\n");
          for(int i=1;i<=n+m;i++) 
          {
              int x=Q.top();Q.pop();
              if(i%t==0)printf("%d ",x+m*q);
          }
          printf("\n");
          return 0;
      }
      

      3个队列100分代码:

      #include<bits/stdc++.h>
      using namespace std;
      const int N=8e6;
      queue<int>q1,q2,q3;
      int n,m,q,u,v,t,delta;
      int a[N];
      int getmax()
      {
          int a=q1.empty()?-2e9:q1.front();
      	int b=q2.empty()?-2e9:q2.front();
      	int c=q3.empty()?-2e9:q3.front();
      	int x=max(a,max(b,c));
          if(x==a)q1.pop();
          else if(x==b)q2.pop();
          else if(x==c)q3.pop();
          return x;
      }
      int main()
      {
          scanf("%d%d%d%d%d%d",&n,&m,&q,&u,&v,&t);
          double p=(double)u/v;
          for(int i=1;i<=n;i++)scanf("%d",&a[i]);
          sort(a+1,a+n+1);
          for(int i=n;i>=1;i--)q1.push(a[i]);
          for(int i=1;i<=m;i++)
          {
          	int x=getmax()+(i-1)*q;
              if(i%t==0)printf("%d ",x);
              q2.push(int(p*x)-i*q);
      		q3.push(x-int(p*x)-i*q);
          }
      	printf("\n");
          for(int i=1;i<=n+m;i++) 
          {
              int x=getmax()+m*q;
              if(i%t==0)printf("%d ",x);
          }
          printf("\n");
          return 0;
      }
      
      • 1

      信息

      ID
      6386
      时间
      1000ms
      内存
      512MiB
      难度
      10
      标签
      递交数
      7
      已通过
      4
      上传者