hdu 4262 Juggler 这题真是跟小丑一般。。。
来源:互联网 发布:java默认的编码方式 编辑:程序博客网 时间:2024/04/27 20:02
题意:
有个球的圈圈。三种操作:逆时针转一个,顺时针转一个,丢掉手中的那个的同时顺时针的球到你的手里。每个操作都花费一秒。告诉你要求的出圈顺序,求最小花费时间。注:开始在手中的球为1.
解:
线段树和树状数组都可。树状数组很蛋疼。建议我以后用线段树。开始为什么不用线段树是因为怕自己搞不出相对坐标和绝对坐标。凡是二分的树状数组能不写就不写。
这个是用set代替二分的代码,建议以后迫不得已要用二分的时候就用set。
/*Pro: 0Sol:date:*/#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#include <cmath>#include <queue>#include <set>#include <vector>#define maxn 100010#define lson l, m, rt << 1#define rson m + 1, r, rt << 1 | 1#define ls rt << 1#define rs rt << 1 | 1using namespace std;int n,now,c[maxn],pre,suf,alre,out,in;__int64 ans;struct query{ int id, ord;}q[maxn];bool cmpx(query a,query b){ return a.ord < b.ord;//ord是时间}int getsum(int pos){ int sum = 0; while(pos){ sum += c[pos]; pos -= (pos & -pos); }return sum;}void modify(int pos){ while(pos <= n){ c[pos] += 1; pos += (pos & -pos); }}set <int> S;set <int> :: iterator it;int main(){ while(~scanf("%d",&n) && n){ memset(c,0,sizeof(c));//0 表示在手里, 1 表示已经出去了 id建边 S.clear(); for(int i = 1; i <= n; i ++){ scanf("%d",&q[i].ord); q[i].id = i; S.insert(i); } sort(q + 1, q + n + 1, cmpx); now = 1; ans = 0; alre = 0; for(int i = 1; i <= n; i ++){ // cout<<now<<" "<<q[i].id<<endl; if(now > q[i].id) { pre = q[i].id; suf = now; }else{ pre = now; suf = q[i].id; } pre = pre - getsum(pre);//表示前面有多少个0,多少个还在,包括本身 suf = suf - getsum(suf); in = suf - pre; out = n - alre - in; ans+=min(in,out)+1; alre ++; if(alre==n)break; S.erase(q[i].id); if(S.lower_bound(q[i].id)!=S.end()) { it=S.lower_bound(q[i].id); } else { it=S.lower_bound(0); } now = *it ; } cout<<ans<<endl; }return 0;}这个是改出来的二分。老娘虚脱了。
/*Pro: 0Sol:date:*/#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#include <cmath>#include <queue>#include <set>#include <vector>#define maxn 100010#define lson l, m, rt << 1#define rson m + 1, r, rt << 1 | 1#define ls rt << 1#define rs rt << 1 | 1using namespace std;int n,now,c[maxn],pre,suf,alre,out,in;__int64 ans;struct query{ int id, ord;}q[maxn];bool cmpx(query a,query b){ return a.ord < b.ord;//ord是时间}int getsum(int pos){ int sum = 0; while(pos){ sum += c[pos]; pos -= (pos & -pos); }return sum;}void modify(int pos){ while(pos <= n){ c[pos] += 1; pos += (pos & -pos); }}int bs(int l,int r){ int mid,flag=l; while(l + 1< r) { mid=(l+r)>>1; if(getsum(mid)-getsum(l)==mid-l) { l=mid; } else { r=mid; } } if(getsum(l)-getsum(flag)==l-flag) { return r; } return l;}int main(){ while(~scanf("%d",&n) && n){ memset(c,0,sizeof(c));//0 表示在手里, 1 表示已经出去了 id建边 for(int i = 1; i <= n; i ++){ scanf("%d",&q[i].ord); q[i].id = i; } sort(q + 1, q + n + 1, cmpx); now = 1; ans = 0; alre = 0; for(int i = 1; i <= n; i ++){ if(now > q[i].id) { pre = q[i].id; suf = now; }else{ pre = now; suf = q[i].id; } pre = pre - getsum(pre);//表示前面有多少个0,多少个还在,包括本身 suf = suf - getsum(suf); in = suf - pre; out = n - alre - in; ans+=min(in,out)+1; alre ++; if(alre==n)break; modify(q[i].id); if(getsum(n)-getsum(q[i].id)==n-q[i].id) { now= bs(0,q[i].id);//边界值问题需要处理一下 } else { now= bs(q[i].id,n); } } cout<<ans<<endl; }return 0;}
线段树代码: 其实我写过一遍类似的poj 2886,当时就是照着别人的代码敲的,还以为自己会了呢,但是发觉理解得还是不够深啊。。。别人的和自己的就是不一样啊。要把别人的学到手!!!
#include <cstdio>#include <algorithm>using namespace std;#define lson l,m,rt << 1#define rson m + 1 , r, rt <<1 | 1#define havem int m = (l + r) >> 1#define ls rt << 1#define rs rt << 1 | 1#define maxn 100100int sum[maxn << 2];void build(int l, int r, int rt){ if(l == r){ sum[rt] = 1; return ; }havem; build(lson); build(rson); sum[rt] = sum[ls] + sum[rs];}void update(int pos, int l, int r, int rt){ if(l == r){ sum[rt] = 0; return ; }havem; if(pos <= m) update(pos,lson); else update(pos,rson); sum[rt] = sum[ls] + sum[rs];}int query(int L,int R, int l, int r, int rt){ if(L <= l && r <= R){ return sum[rt]; }havem; int ans = 0; if(L <= m ) ans = query(L,R,lson); if(R > m) ans += query(L,R,rson); return ans;}struct Qu{ int id,time; bool operator < (const Qu& cmp)const{ return time < cmp.time; }}q[maxn];int getpos(int pos, int l, int r, int rt){//去找从1开始的第pos个人,如果pos这个地方就有人,那么就是他了 if(l == r) return l; havem; if(pos <= sum[ls]) return getpos(pos,lson); return getpos(pos - sum[ls],rson);}int n;int main(){ while(~scanf("%d",&n) && n){ build(1,n,1); for(int i = 1; i <= n; i ++){ scanf("%d",&q[i].time); q[i].id = i; } sort(q + 1, q + 1 + n); int& mod = sum[1];// int now = 1; __int64 ans = 0; for(int i = 1; i <= n; i ++){ int tmp; if(now == q[i].id){ ans += 1; }else if(now < q[i].id){ tmp = query(now + 1,q[i].id,1,n,1); ans += min(tmp,mod - tmp) + 1; }else{ tmp = query(q[i].id,now - 1,1,n,1); ans += min(tmp,mod - tmp) + 1; } update(q[i].id,1,n,1); int Left = query(1,q[i].id,1,n,1); if( Left < mod ){ //左边小于剩下的人数,说明右边有人,就去右边找 now = getpos(Left + 1,1,n,1);//去找剩下的Left+1个人 }else{ //从后面找第一个1 now = getpos(1,1, n, 1); } } printf("%I64d\n",ans); } return 0;}
- hdu 4262 Juggler 这题真是跟小丑一般。。。
- HDU 4262 Juggler(线段树)
- HDU 4262 Juggler (模拟+线段树优化)
- hdu 4262 Juggler(树状数组)
- TOJ 4354 HDU 4262 Juggler / 树状数组
- 小丑
- 小丑
- HDU4262 Juggler
- Starling Juggler
- 还真是神一般的定义啊
- 小丑排序
- 这几天真是一言难尽!
- 这年代真是的
- 真是。。。。。。。。。。。。。。。。
- hdu 5700 难度:一般
- hdu 2795 难度:一般
- HDU 5071 Chat (神一般的模拟题)
- 【HDU 1686】KMP+贪心 剪花布条(一般题)
- Flexigrid例子二: 原位编辑器
- Windows 下搭建 Git Server
- 判断一个链表是不是回文数,要求O(n)时间
- curses库的编程
- Delphi 与 C/C++ 数据类型对照表
- hdu 4262 Juggler 这题真是跟小丑一般。。。
- hdu2732最大流
- 杂记
- 遗传算法原理与应用详解
- 如何提高抗压能力和适应能力
- 递归方程的特征方程
- 异步Socket
- Java Portlet入门
- hdu 4260 The End of The World