|
IT CompaniesTime 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.
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.
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.
Sample Input
Sample Output
|
第一次活生生的写了一棵线段树....调了一天代码....不过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|1
using 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|1
using 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;
}