本题中,我们将用符号⌊c⌋ 表示对 c 向下取整,例如:⌊3.0⌋=⌊3.1⌋=⌊3.9⌋=3 。
蛐蛐国最近蚯蚓成灾了!隔壁跳蚤国的跳蚤也拿蚯蚓们没办法,蛐蛐国王只好去请神刀手来帮他们消灭蚯蚓。
蛐蛐国里现在共有 n 只蚯蚓( n 为正整数)。每只蚯蚓拥有长度,我们设第 i 只蚯蚓的长度为 ai (i=1,2,…,n ),并保证所有的长度都是非负整数(即:可能存在长度为 0 的蚯蚓)。
每一秒,神刀手会在所有的蚯蚓中,准确地找到最长的那一只(如有多个则任选一个)将其切成两半。神刀手切开蚯蚓的位置由常数 p (是满足 0 < p<1 的有理数)决定,设这只蚯蚓长度为 x ,神刀手会将其切成两只长度分别为 floor⌊px⌋ 和 x−⌊px⌋ 的蚯蚓。特殊地,如果这两个数的其中一个等于 0 ,则这个长度为 0 的蚯蚓也会被保留。此外,除了刚刚产生的两只新蚯蚓,其余蚯蚓的长度都会增加 q (是一个非负整常数)。
蛐蛐国王知道这样不是长久之计,因为蚯蚓不仅会越来越多,还会越来越长。蛐蛐国王决定求助于一位有着洪荒之力的神秘人物,但是救兵还需要 m 秒才能到来……( m 为非负整数)
蛐蛐国王希望知道这 m 秒内的战况。具体来说,他希望知道:
m 秒内,每一秒被切断的蚯蚓被切断前的长度(有 m 个数);
m 秒后,所有蚯蚓的长度(有 n+m 个数)。
蛐蛐国王当然知道怎么做啦!但是他想考考你……
输入格式:
输入格式:
第一行包含六个整数n,m,q,u,v,t ,其中:n,m,q 的意义见问题描述; u,v,t 均为正整数;你需要自己计算 p=u/v (保证 0
3 7 1 1 3 1
3 3 2
样例输出:
3 4 4 4 5 5 6
6 6 6 5 5 4 4 3 2 2
1.先就想到了set,于是就用了set于是就写了一个智障代码,CE,因为set只能用迭代器..
#include
#include
#include
using namespace std;
int main(){
set<int> s;
int n,m,q,u,v,t;
cin>>n>>m>>q>>u>>v>>t;
for(int i=1;i<=n;i++){
int a;
cin>>a;
s.insert(a);
}
double p=u/v;
for(int i=1;i<=m;i++){
int t2=s[n+m-2];
if(i%t==0)cout<2]<<" ";
s.erase(s[m+n-2]);
for(int i=m+n-3;i>=0;i--)s[i]+=q;
s.insert(int(p*t2));
s.insert(t2-int(p*t2));
}
cout<for(int i=1;i<=n;i++){
if(i%t==0)cout<return 0;
}
set是从小到大排序且set的迭代器不可以执行it+变量,只能用it++运算符,所以我就写了一个结构体,重载<运算符,如下
struct QY{
int l;
bool operator < (const QY& b)const{
if(this->l>b.l)return true;
return false;
}
};
总算是有一个从大到小的序列了,但是set有一个问题就是,集合是不可重复的!所以又写了一个map记录一个长度出现了多少次如果次数为0就在set里删除元素,于是就有了:
void myinsert(QY a){
if(!cnt.count(a.l)){cnt[a.l]=0;s.insert(a);}
cnt[a.l]++;
return;
}
void myerase(QY a){
cnt[a.l]--;
if(cnt[a.l]==0){cnt.erase(a.l);s.erase(a);}
return;
}
然后就是一波模拟,但是map慢。。。TLE了13组,所以说这是不可行的
#include
#include
#include
#include
using namespace std;
map<int,int>cnt;
struct QY{
int l;
bool operator < (const QY& b)const{
if(this->l>b.l)return true;
return false;
}
};
set s;
void myinsert(QY a){
if(!cnt.count(a.l)){cnt[a.l]=0;s.insert(a);}
cnt[a.l]++;
return;
}
void myerase(QY a){
cnt[a.l]--;
if(cnt[a.l]==0){cnt.erase(a.l);s.erase(a);}
return;
}
int main(){
int n,m,q,u,v,t;
cin>>n>>m>>q>>u>>v>>t;
double p=u/v;
for(int i=1;i<=n;i++){
QY tmp;
scanf("%d",&tmp.l );
myinsert(tmp);
}
set ::iterator it;
for(int i=1;i<=m;i++){
it=s.begin();
QY tmp=*it;
if(i%t==0)printf("%d ",tmp.l);
myerase(tmp);
for(it=s.begin();it!=s.end();it++){
QY tmp2=*it;
tmp2.l +=q;
}
tmp.l=t*p;
myinsert(tmp);
tmp.l=t-tmp.l;
myinsert(tmp);
}
cout<for(int i=1;i<=n+m;it++){
QY tmp=*it;
for(int j=0;jif(i%t==0){printf("%d ",tmp.l);}
}
}
return 0;
}
map慢让我们不得不去找一种其他方法
1.pair<数据,出现次数>
2.结构体里加个出现出现次数
但两个办法有个问题就是set查找会出现查不了,因为查的时候不知道出现次数s.count()括号里数据类型是结构体或pair而参数数不全是不可以的
所以set不行
再想有什么类似于set但数据可重复?
优先队列!
但是有一个问题是优先队列没有指针!不可能用迭代器的方式修改数据(增加蚯蚓长度)当然,可以加一个时间戳(入队时间),就像lazy标记一样在使用时加上((当前时间-时间戳)*q),但是时间戳怎么存呢?这回连map都不行了,长度一样时间戳可能不同!,所以不可行,还有办法,例如
在时间为i的时候要入队,那么就给这个要入队的数据减去i*q那么在出队的时候我就认为他是在开始时入队的,加上出队时间*q正好抵消掉减的那一部分了,而且后来者数据就是小不需要考虑因为延时带来的出队出错!至于优先队列的常数大,会被卡,最多80分(开了O2优化也是),这是我们可以用下面的三队列的方法
#include
#include
#include
#include
using namespace std;
priority_queue<int> que;
int m,n,q,u,v,t,add=0;
int main(){
cin>>n>>m>>q>>u>>v>>t;
for(int i=1;i<=n;i++){
int tmp;
scanf("%d",&tmp);
que.push(tmp);
}
for(int i=1;i<=m;i++){
int tmp=que.top();
que.pop();
tmp+=add;
int a=(long long)tmp*u/v;
int b=tmp-a;
que.push(a-add-q);
que.push(b-add-q);
if(i%t==0)printf("%d ",tmp);
add+=q;
}
printf("\n");
for(int i=1;i<=n+m;i++){
if(i%t==0)printf("%d ",que.top()+add);
que.pop();
}
return 0;
}
还有办法:
假设有两只蚯蚓长度分别为x,y,且x>y;那么根据题意x一定被先切,于是我们假设y在x被切后i秒被切。
假设x被切成x1和x2两段,y被切成y1和y2两段;
假设x1>x2 y1>y2随便写的,这个关系怎么写都可以
那么x1>y1,x2>y2
于是我们开3个队列
qs存储未被切的,(已从大到小排序)
q1存储 p*x,
q2存储 x-p*x;
由前面可得每个队列都是单调的(此处即由大到小的)
于是每次取3个堆首的最大元素模拟即可
关于时间戳同上
#include
#include
#include
#include
#include
using namespace std;
queue<int>qq,q1,q2;
int n,m,q,u,v,t,tmp[100050],add=0;
int cmp(int a,int b){return a>b;}
int getfront(queue<int> &q){
if(q.empty())return -0x3f3f3f3f;
return q.front()+add;
}
int compare_each_front(){
int a=getfront(qq),b=getfront(q1),c=getfront(q2);
int maxn=max(a,max(b,c));
if(maxn==a) qq.pop();
else if(maxn==b) q1.pop();
else if(maxn==c) q2.pop();
return maxn;
}
int main(){
cin>>n>>m>>q>>u>>v>>t;
for(int i=0;iscanf("%d",&tmp[i]);
sort(tmp,tmp+n,cmp);
for(int i=0;ifor(int i=1;i<=m;i++,add+=q){
int tmp=compare_each_front();
int a=(long long)tmp*u/v;
int b=tmp-a;
q1.push((int)a-add-q);
q2.push((int)b-add-q);
if(i%t==0)cout<" ";
}
cout<for(int i=1;i<=n+m;i++){
int tmp=compare_each_front();
if(i%t==0)printf("%d ",tmp);
}
return 0;
}