hdu(5565)——Clarke and baton
来源:互联网 发布:抢任务软件 编辑:程序博客网 时间:2024/05/07 19:36
这道题比赛的时候看了一下题,以为用优先队列能过,没想到常数过大,所以T了= =
题意:
现在有n个人,每个人有一个体重值w[i],然后,每次都可以使体重最大的那个人的体重值减少1,如果有多个体重值相同的人,那么就使序号最小的那个人体重值减少1,然后就这样进行q次,最后让你输出它们变化后的体重+它们的序号的异或和。
思路:
1)我是按照官方题解写的,首先开两个可变数组a,b,a是用来存体重是i的人的序号,b是用来存体重为i的人他的体重减少1之后的序号。
然后类似于归并排序那样,模拟一下,然后最后再更新一下w[i]中的体重值,就好啦。。。但是由于貌似开了两个vector的原因,竟然MLE了。。。(听说好像是服务器的问题,反正迷= =)
2)参考了一下别人的写法,发现这就是一道小模拟题。
首先,我们先存进去每个体重的人数是几个,然后从大到小进行枚举体重,然后num代表的是现在已经进行了几次减1的操作(num也就是作为累加的计数器的作用)。如果q-num<=0的话,那么说明当前体重的人数已经大于剩下的操作数了,所以我们不用再q-num了。
例如:
假设n=6,q=6;
a[3]={1,2}
a[2]={3,5,6}
a[3]={4}
那么,当i=3时,num=2,q=4;i=2时,num=5(因为此时之前3的人都移到2这里了),此时q-sum<=0,所以接下来我们只需要在选出4个人就好了(就for一遍,选出序号较小的4个人就好)
1)归并排序(MLE版)(如果有哪位大神可以帮助我优化一下,那么非常感谢o( ̄▽ ̄)d)
#include<cstdio>#include<cstring>#include<map>#include<set>#include<cmath>#include<algorithm>#include<vector>#include<queue>#include<iostream>using namespace std;typedef __int64 ll;typedef unsigned __int64 ULL;#define inf 99999999#define maxn 10000010vector<ll> a[maxn],b[maxn];vector<ll>::iterator it;vector<ll>::iterator it2;ll w[maxn];ll seed;int rand(int l,int r){ static __int64 mo=1e9+7,g=78125; return l+((seed*=g)%=mo)%(r-l+1);}int main(){ int T; scanf("%d",&T); while(T--){ int n,q; scanf("%d%d%I64d",&n,&q,&seed); int sum=rand(q,10000000); ll wmax=0; for(int i=1;i<=n;i++){ w[i]=rand(0,sum/(n-i+1)); sum-=w[i]; wmax=max(wmax,w[i]); } int tmp=rand(1,n); w[tmp]+=sum; wmax=max(wmax,w[tmp]); for(int i=1;i<=n;i++){ a[w[i]].push_back(i); } while(q--){ if(a[wmax].size()==0&&b[wmax].size()==0){ wmax--; } ll aa=0,bb=0; if(!a[wmax].empty()) it=a[wmax].begin(),aa=*it; if(!b[wmax].empty()) it2=b[wmax].begin(),bb=*it2; int len1=a[wmax].size(),len2=b[wmax].size(); int f1=0,f2=0; if(len2==0||(len1&&aa<bb)){ b[wmax-1].push_back(aa); a[wmax].erase(a[wmax].begin()); } else{ b[wmax-1].push_back(bb); b[wmax].erase(b[wmax].begin()); } } for(int i=wmax-3;i<=wmax;i++){ for(int j=0;j<a[i].size();j++) w[a[i][j]]=i; for(int j=0;j<b[i].size();j++) w[b[i][j]]=i; } ll ans=0; for(int i=1;i<=n;i++){ ans=ans^(w[i]+i); } printf("%I64d\n",ans); } return 0;}/*13 2 1*/
2)模拟法
#include<cstdio>#include<cstring>#include<map>#include<set>#include<cmath>#include<algorithm>#include<vector>#include<queue>#include<iostream>using namespace std;typedef __int64 ll;typedef unsigned __int64 ULL;#define inf 99999999#define maxn 10000010map<int,int> mp;int w[maxn];ll seed;int rand(int l,int r){ static __int64 mo=1e9+7,g=78125; return l+((seed*=g)%=mo)%(r-l+1);}int main(){ int T; scanf("%d",&T); while(T--){ mp.clear(); int n,q; scanf("%d%d%I64d",&n,&q,&seed); int sum=rand(q,10000000); int wmax=0; for(int i=1;i<=n;i++){ w[i]=rand(0,sum/(n-i+1)); mp[w[i]]++; sum-=w[i]; wmax=max(wmax,w[i]); } int tmp=rand(1,n); mp[w[tmp]]--; w[tmp]+=sum; mp[w[tmp]]++; wmax=max(wmax,w[tmp]); int num=0; for(int i=wmax;i>=0;i--){ num+=mp[i]; if(q-num<=0){ int ans=0; for(int j=1;j<=n;j++){ if(w[j]<i){ ans=ans^(w[j]+j); } else if(q){ ans=ans^(i-1+j); q--; } else{ ans=ans^(i+j); } } printf("%d\n",ans); break; } q-=num; } } return 0;}/*13 2 1*/
0 0
- hdu(5565)——Clarke and baton
- HDU 5565:Clarke and baton
- HDU 5565 Clarke and baton
- hdu 5565 Clarke and baton
- HDU 5565 - Clarke and baton (思维)
- hdu 5565 Clarke and baton(水)
- BestCoder Round #62 (div.2) D.Clarke and baton
- HDU Clarke and points
- Clarke and MST HDU
- BestCoder Round #62 (div.2)-Clarke and baton(二分搜索)
- HDU 5463 Clarke and minecraft
- HDU 5465 Clarke and puzzle
- HDU 5463 Clarke and minecraft
- HDU 5463 Clarke and minecraft
- HDU 5464:Clarke and problem
- HDU 5463Clarke and minecraft
- HDU 5465 Clarke and puzzle
- HDU 5464 Clarke and problem
- 单片机秒表程序(自动切换时间
- java中的HashSet集合
- 首次开通个人博客!
- intent与intent filter学习
- activemq 如何开启死信队列
- hdu(5565)——Clarke and baton
- 基于React Native的android开发框架搭建
- 拉低程序员工作效率的编程习惯
- Java微观探源(三)_虚拟机调优之工具十问
- Spring事务配置的五种方式
- vector基本用法
- 理解SWT监听器----匿名内部类
- 算法练习三:从尾到头打印链表
- C++ 09原型模式