hdu4446 IT Companies
来源:互联网 发布:三星手机数据恢复 编辑:程序博客网 时间:2024/06/09 22:55
IT Companies
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 178 Accepted Submission(s): 48
Problem Description
There are N IT companies which are labeled from 1 to N. Each of them has a branch (a branch is not a company, and companies and branches are all called "unit").The branches are labeled from -1 to –N. The branch of company i is labeled as -i. The number of workers of each company and its branch has to fit the rules below:
1. The number of workers of a company must be larger than that of the branch of it.
2. There are more workers in company i than company j if and only if there are more workers in the branch of company i than the branch of company j.
Among the companies whose label is larger than i(range from i+1 to n),and the branches whose label is larger than -i (range from -1 to –(i-1) ), there are c[i] units which have more workers than company i.
You need to sort the 2×N units in the ascending order by the number of workers.
1. The number of workers of a company must be larger than that of the branch of it.
2. There are more workers in company i than company j if and only if there are more workers in the branch of company i than the branch of company j.
Among the companies whose label is larger than i(range from i+1 to n),and the branches whose label is larger than -i (range from -1 to –(i-1) ), there are c[i] units which have more workers than company i.
You need to sort the 2×N units in the ascending order by the number of workers.
Input
The input contains multiple test cases. Each test case begins with a single line containing one integer N indicating the number of companies (0 < N ≤ 100000). Next line contains N integers which are c[1],c[2]…c[N] (c[i] ≤ N).
The input ends with N = 0.
The input ends with N = 0.
Output
For each test case, output the sorted label sequence of all units in a line. If there are no solutions, output "Impossible" instead.
This problem is special judged.
This problem is special judged.
Sample Input
21 1104 8 3 4 2 0 5 7 1 60
Sample Output
Impossible-8 -2 -10 -7 8 2 10 -4 7 -1 4 -3 -5 -9 1 3 5 9 -6 6
第一次活生生的写了一棵线段树....调了一天代码....不过ac的时候还是好开心啊好开心^-^
构造用的是官方题解:
1.一开始开2个队列a,b。a为答案队列,b为临时队列
2.找出当最小的C值为C[k](相同时取k最小的)
a)C[k]=0:将k加入a,-k加入b。在C序列中删除元素C[k],并将C[1]到C[k-1]减一。
b)C[k]>0:将b队首的元素p取出加入a,并将C[-p+1]到c[n]减一。
重复做直到所有元素进入a或者b
3.将b接在a后面,倒序就是答案序列
无解有两种情况:
1.C中出现了负数。
2.出现2b情况时b为空
这种构造显然不是我能想到的....我好好把线段树写出来就万岁了...#include <iostream>#include <queue>#include <cstring>#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1using namespace std;const int ma=1000010;const int inf=1<<25;int n;int c[ma<<2];int rc[ma];int add[ma<<2];int rrt;void pushup(int rt){ c[rt]=min(c[rt<<1],c[rt<<1|1]);}void pushdown(int rt,int m){ if(add[rt]) { add[rt<<1]+=add[rt]; add[rt<<1|1]+=add[rt]; c[rt<<1]+=add[rt]; c[rt<<1|1]+=add[rt]; add[rt]=0; }}void build(int l,int r,int rt){ add[rt]=0; if(l==r) { scanf("%d",&c[rt]); return ; } int m=(l+r)>>1; build (lson); build (rson); pushup(rt);} int query(int l,int r,int rt){ if(l==r){rrt=rt;return l;} pushdown(rt,r-l+1); int m=(l+r)>>1; if(c[rt<<1]<=c[rt<<1|1]) return query(lson); else return query(rson);}void update(int L,int R,int l,int r,int rt){ if(L<=l&&r<=R) { add[rt]--; c[rt]--; return ; } pushdown(rt,r-1+1); int m=(l+r)>>1; if(L<=m) update(L,R,lson); if(m<R)update(L,R,rson); pushup(rt);}void update2(int p,int l,int r,int rt){ if(l==r) { c[rt]=inf; return ; // cout<<"update2"<<rt<<endl; } int m=(l+r)>>1; if(p<=m)update2(p,lson); else update2(p,rson); pushup(rt);} int main(){ while(scanf("%d",&n),n) { int id=0; int flag=0; build(1,n,1); queue <int> a; queue <int> b; while(a.size()+b.size()!=2*n) { int qq=query(1,n,1); //cout<<qq<<" "<<c[rrt]<<endl; if(c[rrt]<0) { flag=1;break; } if(c[rrt]==0) { a.push(qq); // cout<<"if"<<rrt<<"qq"<<qq<<endl; b.push(-qq); if(qq!=1) update(1,qq-1,1,n,1); update2(qq,1,n,1); // cout<<qq<<" "<<c[rrt]<<endl; // cout<<"what"<<c[3]<<endl; } else { // cout<<"else"<<b.size()<<endl; if(b.size()==0){flag=1;break;} int t=b.front(); // cout<<"what"<<c[3]<<endl; if(-t<n) update(-t+1,n,1,n,1); // cout<<"what"<<c[3]<<endl; b.pop(); a.push(t); } } if(flag) { printf("Impossible\n"); }else{ int d[200010]; int i=0; while(a.size()!=0) {d[i++]=a.front();a.pop();} while(b.size()!=0) {d[i++]=b.front();b.pop();} //printf("%d",d[2*n-1]); for(i=2*n-1;i>=0;i--) printf("%d ",d[i]); puts(""); } } return 0; }
里面各种调代码的痕迹无视就好...一直错在update的时候上下界如果超了,就会出一些奇怪的问题....不知道为什么会出那些问题,不过加上if判断就好了.
写起来就是普通的线段树,不过我用的法子比较笨,同时用了区间更新和单点更新....因为对线段树还是不太熟....其实现在一想用一个应该就够了...update是区间减一,update2是把单点设为无穷大.查询是全部数找最小值.
....这么简单的东西我到底是怎么写了一天的T-T...
顺手把update2这种奇怪的东西弄掉了...
#include <iostream>#include <queue>#include <cstring>#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1using namespace std;const int ma=1000010;const int inf=1<<25;int n;int c[ma<<2];int rc[ma];int add[ma<<2];int rrt;void pushup(int rt){ c[rt]=min(c[rt<<1],c[rt<<1|1]);}void pushdown(int rt,int m){ if(add[rt]) { add[rt<<1]+=add[rt]; add[rt<<1|1]+=add[rt]; c[rt<<1]+=add[rt]; c[rt<<1|1]+=add[rt]; add[rt]=0; }}void build(int l,int r,int rt){ add[rt]=0; if(l==r) { scanf("%d",&c[rt]); return ; } int m=(l+r)>>1; build (lson); build (rson); pushup(rt);} int query(int l,int r,int rt){ if(l==r){rrt=rt;return l;} pushdown(rt,r-l+1); int m=(l+r)>>1; if(c[rt<<1]<=c[rt<<1|1]) return query(lson); else return query(rson);}void update(int L,int R,int l,int r,int rt,int ad){ if(L<=l&&r<=R) { add[rt]+=ad; c[rt]+=ad; return ; } pushdown(rt,r-1+1); int m=(l+r)>>1; if(L<=m) update(L,R,lson,ad); if(m<R)update(L,R,rson,ad); pushup(rt);}int main(){ while(scanf("%d",&n),n) { int id=0; int flag=0; build(1,n,1); queue <int> a; queue <int> b; while(a.size()+b.size()!=2*n) { int qq=query(1,n,1); //cout<<qq<<" "<<c[rrt]<<endl; if(c[rrt]<0) { flag=1;break; } if(c[rrt]==0) { a.push(qq); // cout<<"if"<<rrt<<"qq"<<qq<<endl; b.push(-qq); if(qq!=1) update(1,qq-1,1,n,1,-1); update(qq,qq,1,n,1,inf); // cout<<qq<<" "<<c[rrt]<<endl; // cout<<"what"<<c[3]<<endl; } else { // cout<<"else"<<b.size()<<endl; if(b.size()==0){flag=1;break;} int t=b.front(); // cout<<"what"<<c[3]<<endl; if(-t<n) update(-t+1,n,1,n,1,-1); // cout<<"what"<<c[3]<<endl; b.pop(); a.push(t); } } if(flag) { printf("Impossible\n"); }else{ int d[200010]; int i=0; while(a.size()!=0) {d[i++]=a.front();a.pop();} while(b.size()!=0) {d[i++]=b.front();b.pop();} //printf("%d",d[2*n-1]); for(i=2*n-1;i>=0;i--) printf("%d ",d[i]); puts(""); } } return 0; }
- hdu4446 IT Companies
- hdu4446 IT Companies
- hdu4446 IT Companies(线段树)
- Cool IT Companies
- The death of IT companies in education I
- HDU 4446 IT Companies (线段树, 区间修改)
- Controlling Companies
- creative companies
- Controlling Companies
- Controlling Companies
- Sue Companies, Not Coders
- fjnu 1148 Controlling Companies
- 【其他】【USACO】Controlling Companies
- Development Tool Companies
- usaco Controlling Companies
- USACO Controlling Companies DFS
- usaco Controlling Companies
- USACO Controlling Companies
- Linux下ffmpeg视频转码的几个例子
- NoSQL总结分类
- Android高手进阶教程(二十六)之---Android超仿Path菜单的实现!
- ffmpeg参数
- 怎么样才能稳定使用google 搜索?
- hdu4446 IT Companies
- Android高手进阶教程(二十七)之---基于ViewFlipper实现的自定义新手指引控件.
- Linux C/C++ GDB教程详解
- Android高手进阶教程(二十八)之---Android ViewPager控件的使用(基于ViewPager的横向相册)!!!
- NoSQL 数据建模技术
- linux 端tomcat监控程序(JAVA版)
- java调用linux命令传递参数问题
- 谈谈Android里的Context的使用!!!
- Eclipse中配置Hibernate