您的位置:首页 > 其它

UOJ264 NOIP2016 day2 T2 蚯蚓(队列)

2017-09-20 14:54 471 查看

UOJ264 NOIP2016 day2 T2 蚯蚓

原题地址http://uoj.ac/problem/264

题意:

本题中,我们将用符号 ⌊c⌋ 表示对 c 向下取整,例如:⌊3.0⌋=⌊3.1⌋=⌊3.9⌋=3。

蛐蛐国里现在共有 n 只蚯蚓(n 为正整数)。每只蚯蚓拥有长度,我们设第 i 只蚯蚓的长度为 ai (i=1,2,…,n),并保证所有的长度都是非负整数(即:可能存在长度为 0 的蚯蚓)。

每一秒,神刀手会在所有的蚯蚓中找到最长的那一只(如有多个则任选一个)将其切成两半。神刀手切开蚯蚓的位置由常数 p(是满足 0< p<1 的有理数)决定,设这只蚯蚓长度为 x,神刀手会将其切成两只长度分别为 ⌊px⌋ 和 x−⌊px⌋ 的蚯蚓。特殊地,如果这两个数的其中一个等于 0,则这个长度为 0 的蚯蚓也会被保留。此外,除了刚刚产生的两只新蚯蚓,其余蚯蚓的长度都会增加 q(是一个非负整常数)。

蛐蛐国王决定求助于一位有着洪荒之力的神秘人物,但是救兵还需要 m 秒才能到来……(m 为非负整数)。

蛐蛐国王希望知道这 m 秒内的战况。具体来说,他希望知道:

m 秒内,每一秒被切断的蚯蚓被切断前的长度(有 m 个数);

m 秒后,所有蚯蚓的长度(有 n+m 个数)。

数据范围

保证 1≤n≤1e5,0≤m≤7×1e6

0< u < v≤1e9,0≤q≤200,1≤t≤71,0≤ai≤1e8。

题解:

虽说暴力又好想又好写,但是正解真的很妙。

假设有x,y两只蚯蚓,满足len x>=len y,x被切的两部分分别为a1,b1,y被切的两部分分别为a2,b2。那么有一个性质 a1>=a2 ,b1>=b2。

想一下,a1+b1=(原)x,a2+b1=(原)y。

时间对他们的作用是相同的,又因为均是成比例切开,因此仍然满足原来的大小关系。

因此,我们可以不必维护堆,因为其本身就有单调性。

维护三个队列 Q0,Q1,Q2。Q1存放原来的大小顺序,Q2存放切出的所有a部分,Q2存放切出的所有b部分。每次只需取三个队队首最大的那个,再把切出来的两个部分放入对应队队尾即可。

注意维护时间戳(保存距离上一次被切过了多少秒)来算现在的长度。

代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
const int N=100010;
const int M=7000010;
int n,m,q,u,v,t;
struct node
{
int len,cnt;
node(int len,int cnt): len(len),cnt(cnt){}
};
queue<node> Q[3];
int ll
;
void solve()
{
int kk=0;
for(int inc=1;inc<=m;inc++)
{
int opt=-1; int mx=-1;
for(int i=0;i<3;i++)
{
if(!Q[i].empty()&&(Q[i].front().len+(inc-1-Q[i].front().cnt)*q>mx))
{mx=Q[i].front().len+(inc-1-Q[i].front().cnt)*q; opt=i;}
}
node tmp= Q[opt].front(); Q[opt].pop();
int len=tmp.len+(inc-1-tmp.cnt)*q;
kk++;
if(kk%t==0)
{
printf("%d",len);
if(kk!=(m/t)*t)  printf(" ");
}
int s1=(1LL*len*u)/v; int s2=len-s1;
Q[1].push(node(s1,inc)); Q[2].push(node(s2,inc));
}
printf("\n");
}
void print()
{
int kk=0;
while(1)
{

if(Q[0].empty()&&Q[1].empty()&&Q[2].empty()) break;
int opt=-1; int mx=-1;
for(int i=0;i<3;i++)
{
if(!Q[i].empty()&&(Q[i].front().len+(m-Q[i].front().cnt)*q>mx))
{mx=Q[i].front().len+(m-Q[i].front().cnt)*q; opt=i;}
}
node tmp= Q[opt].front(); Q[opt].pop();
int len=tmp.len+(m-tmp.cnt)*q;
kk++;
if(kk%t==0)
{
printf("%d",len);
if(kk!=((m+n)/t)*t)  printf(" ");
}
}
printf("\n");
}
int main()
{
scanf("%d%d%d%d%d%d",&n,&m,&q,&u,&v,&t);
for(int i=1;i<=n;i++)
scanf("%d",&ll[i]);
sort(ll+1,ll+n+1);
for(int i=n;i>=1;i--)
Q[0].push(node(ll[i],0));
solve();
print();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: