hdu4446 IT Companies

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.
 

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
      
      
2 1 1 10 4 8 3 4 2 0 5 7 1 6 0
 

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,ba为答案队列,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后面,倒序就是答案序列

无解有两种情况:

1C中出现了负数。

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; 
}
            
        



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值