UOJ264 NOIP2016 day2 T2 蚯蚓(队列)

来源:互联网 发布:军用望远镜软件下载 编辑:程序博客网 时间:2024/05/21 04:42

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[N];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;}
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 球兰叶子发黄软怎么办 蟹爪莲叶子发红怎么办 保险箱没电了打不开怎么办 宁波臭冬瓜酸的怎么办 甜酒酿做了酸了怎么办 孕妇喝了醪糟汤怎么办 鱼侧翻但又没死怎么办 原汁机盖子卡死怎么办 惠人原汁机坏了怎么办 泡芙鸡蛋加多了怎么办 淡奶油打过了怎么办 淡奶油打发过了怎么办 雷神锤子被捏碎怎么办 私处毛很多很黑怎么办 脸上长黑色的毛怎么办 十字军之王2毁容怎么办 多囊卵巢综合症想怀孕怎么办 12306账户名忘了怎么办 丧尸病毒爆发了怎么办 看了鬼故事害怕怎么办 微信验证码忘了怎么办 微拉美后脸变形怎么办 感情不好心好累怎么办 刚买乌龟不吃食怎么办 新小乌龟不吃食怎么办 吃太多了好难受怎么办 已经吃了苦丝瓜怎么办 墨兰叶子尖发黄怎么办 气膜建筑停电了怎么办 脖子转一下就痛怎么办 手抄报空的地方怎么办 20多岁白发很多怎么办 被红火蚁咬了怎么办 现在不能翻墙了怎么办 手机云空间满了怎么办 手机百度云满了怎么办 华为云相册满了怎么办 苹果7icloud满了怎么办 我的世界秒退怎么办 游戏限制ip多开怎么办 棉被被孩子尿了怎么办